Removing items from a multi dimensional array in Java - java

I am trying to remove items from a 3 dimensional array.
I understand that one of the best ways to do this is to convert the array to a list and whilst iterating through the original array remove those items from the list then convert the list back to an array and return it.
I tried this but got an type mismatch when coming back to the array. I suspect I have not done something with the dimensions when converting from array to list.
Advice?
import java.util.List;
import java.util.Arrays;
public class RepatitionRemoval {
public float[][][] process(float[][][] data) {
//this method with step through all of the the strokes and remove
//points which occupy the same position. This should help with time
//warping regconition
//Change the array to a list
List points = Arrays.asList(data);
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
for (int k = 0; k < data[i][j].length-1; k++) {
//if the current coordinate is the same as the one next
//then remove it
if (data[i][j][k] == data[i][j][k+1]) {
points.remove(data[i][j][k]);
}
}
}
}
float[][][] returnData = points.toArray();
return returnData;
}
}

First the following method doesn't do what you think it does:
//Change the array to a list
List points = Arrays.asList(data);
Btw a good IDE will automatically transform that for you to:
List<float[][]> points = Arrays.asList(data);
So when you next do a:
points.remove(data[i][j][k])
what happens is that data[i][j][k] primitive gets auto-boxed to the Float wrapper class and then the remove methods checks to see if it contains any element equal to your wrapped Float. It checks the entire list and doesn't find any Float because... You've got a list of float[][]. So basically your code will never remove any element from the list.
But anyway, you should know that should you find an element that would match in the remove method, you'd get an UnsupportedOperationException because Arrays.asList simply wraps your array and your "list" is still backed the float[][][] array. And you cannot resize arrays.
Then, anyway you typically cannot compare floating point numbers using ==:
if (data[i][j][k] == data[i][j][k+1]) {
for it is ususally a terrible way to check if two floating numbers are equal. Floating numbers should be compared using an epsilon (and you should always keep track of the error propagation).
Regarding your last line, you can cast back to a float[][][] but it's pointless because that list of float[][] you created in the first is backed by your original float[][][] and cannot be modified (well, you may modify individual elements, but you cannot resize it).

List points = Arrays.asList(data);
It's creating list (points) of two dimensional arrays not floats which is what you need.
But the way you are trying to achieve your requirement is not possible and logically invalid.
It sounds like you have to turn your array into list of list of list. Which will logically makes sense when you turn it back into a three dimensional array after removing elements because keeps track of the dimensions.

Is it not because you are trying to push back into a three dimensional array.
You would need to cycle through your array populating the dimensions 2 and 3, 1 by 1.
The whole idea seems overly complex because you would need to know the dimensions after removing the values, I think you are probably best maintaining the 3d array and removing values from that.

Multi-dimensional arrays are arrays of arrays. data is an array of float[][] objects; data[i] is an array of float[] objects, and data[i][j] is an array of float objects. Instead of converting data to a list, you need to convert data[i][j] to a list.
Also, you can't directly remove an item from the list returned by Arrays.asList(), as the list is directly backed by the array, which cannot be resized. Instead, you have to populate an ArrayList, remove the elements, then convert back to an array and replace the original (see this question)
Finally, you're working with an array of primitives (floats), you'll need to convert from float[] to ArrayList<Float> and back again. This isn't trivial; this question may help

Related

User defined Array dimensional and size

I have unsolvable task, I have task, where i have insert random number to array. The user can choose if array is 1D, 2D, 3D,size of array is optional . I tried everything but withot success. I can not use ArrayList.
Thank you for help.
double[] array= new double[size];
for ( int i;i<dimensional;i++)
{
double[] array= new double[size];
}
Edit:
I mind if is effective way to create array with 1D and then add to this array one or more dimension.
Multi-dimensional arrays in java are essentially just arrays of arrays. The user provides the number of dimensions and sizes at runtime so you need to dynamically build this array at this point. It's a strange problem, and not one that you would try to solve with arrays in production code, but nevertheless it should be possible. Try the accepted answer for this question, it seems like a pretty good attempt.
So, an "unsolvable" task ... well, as long as you work with primitive types and the dimension can be theoretically any number (only limited by memory available), you may be right.
You can however use some kind of object (Java is an object-oriented language) and solve the task rather easily. Basically, you might want a tree structure with nodes. You can even write a constructor that sets fixed sizes for every level and give no direct accessors to the array as a whole. Start with:
class Node {
double payload;
Node[] children;
}
I don't really understand what do you want to do with that, but it pretty much fits the idea of N-dimensional array.
Another solution: Make the array one-dimensional, but using the sizes of the individual dimensions, you can calculate the correct index. Of course, it will require you to handle the logic.
E.g. in a 2D array of 3x3 size, you can use a 1D array of 9 size and use first three indexes for first row, next three for second row, last three for third row. You can then use a cycle like this:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//arr[i * 3 + j] = ...
}
}

Techniques to redimension an array in Java : is "nullifying" the array bad?

I'm learning Java and surprisingly I found out that Java arrays are not dynamic - even though its cousing languages have dynamic arrays.
So I came out with ideas to kind of imitate a dynamic array in java on my own.
One thought I had was to copy the original array references to a temporary array, then turn the original array to null, re-set its index to a bigger value and then finally re-copy the values from the temporary array.
Example.:
if(numberOfEntries == array.length){
Type[] temp = new Type[numberOfEntries];
for(int x=0; x < numberOfEntries; x++){
temp[x] = array[x];
}
array = null;
array = new Type[numberOfEntries+1];
for(int x=0; x < numberOfEntries; x++){
array[x] = temp[x];
}
I know that this can result in data loss if the process is interrupted, but aside from that, is this a bad idea? What are my options?
Thanks!
Your idea is in the right ballpark. But for a task that you propose you should never implement your own version, unless it is for academic purposes and fun.
What you propose is roughly implemented by the ArrayList class.
This has an internal array and a size 'counter'. The internal array is filled when items are added. When the internal array is full all elements are copied to a bigger array. The internal array is never released to the user of the class (to make sure it's state is always valid).
In your example code, because an array is a pointer, you don't really need the temp array. Just create a new one, copy all elements and save the pointer to it as your array.
You might want to look into thrashing. Changing the size of the array by 1 is likely to be very inefficient. Depending on your use case, you might want to increase the array size by double, and similarly halve the array when it's only a quarter full.
ArrayList is convenient, but once it's full, it takes linear time to add an element. You can achieve something similar to resizing with the ensureCapacity() method. I'd recommend becoming more familiar with Java's Collections framework so you can make the best decisions in future by yourself.
Arrays are not dynamic their size can't change dynamically and right now you aren't changing the same object, you are replacing smaller size object with larger size object
int[5] Arr = new int[5] ; // Create an array of size 5
Arr = new int[10] ;// you assigned the different objects. It is not the same object.
So, we can't change the size of the array dynamically. You can use ArrayList for the same.
But keep try !!!
Please take a look at java.util.ArrayList which is dynamically, it is part of the Collections framework. Making the Array dynamically should be slower and error-prone.
Have you heard about time complexity , do you know how much time complexity you are increasing, Every time you are copying old array element to new array let you have 1 million element in array then think about copying time of element of one array to another array.
One more thing i want to tell you, ArrayList implementation used same logic except new length that you are using .

Add a value to an array?

I've just created a new array that is one larger than my previous array and I want to copy the values in my first array into my new one. How do I add a new value to the last index of the new array?
This is what I've tried:
public void addTime(double newTime) {
if (numOfTimes == times.length)
increaseSize();
times[numOfTimes] = newTime;
}
I would recommend trying to use an object such as java.util.List rather than raw arrays. Then you can just do:
times.add(newTime) and it handles the sizing for you.
Why not you use System.arraycopy function.
increaseSIze()
{
double [] temp = new double[times.lebgth+1];
System.arrayCopy(times,0,temp,0,times.length);
times=temp;
}
after that you have times array with 1 increased size.
To set a new value to the last index you can do
times[times.length - 1] = newTime;
Array indices go from 0..n-1.
array[array.length - 1] will address the value at the end of the array.
The last item of an array is always at myArray.length - 1. In your case the last element from the times array is times[times.length - 1]. Have a look at http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html for more information about arrays.
But more importantly: If you're trying to change the capacity of your array, you are most likely using the wrong data structure for the job. Have a look at Oracle's Introduction to Collections (and especially the ArrayList class if you need an array-like index to access elements).
why wouldn't you want a java.util.ArrayList for this requirement? Practically, there won't be a need managing its size. You just simply do this:
List<Double> list = new ArrayList<Double>();
list.add(newTime);
Consider Arrays.copyOf if working with arrays is a constraint:
import java.util.Arrays;
...
private void increaseSize() {
// Allocate new array with an extra trailing element with value 0.0d
this.times = Arrays.copyOf( times, times.length + 1 );
}
...
Note that if you are doing this type array management often and in unpredictable ways, you may want to consider one of the Java Collection Framework classes such as ArrayList. One of the design goals of ArrayList is to administer size management, much like the JVM itself administers memory management.
I've developed an online executable example here.

Array of Lists or Other Possibilities?

So my question starts out as being is it possible to make an array of linked lists in Java?
For some background on why I am asking. I am working on a project in which we are given a file of square matrices. We have to find the determinant of the matrices but they have to be stored in a linked structure. We have previously done this same thing using arrays and so I can reuse a decent bit of my source from that one. Here is what I have though up to do (mostly based on my previous project):
Read each line of the file in as a string
Count the number of matrices and determine where each starts and ends.
* Read each element of each matrix into a multi-linked ListNode (I'll write the class for those)
* Repeat for each matrix
Process the determinant of each.
So the two starred steps are the ones I'm having a tough time figuring out. I want to read in all the matrices at once so I don't lose track of where I am in the file like I would if I read in one matrix, did the determinant, and then went back to the file to get another one. However, I don't know how to store each linked list representation so that I can just iteratively process through each. My only thought is to read each matrix into the linked list structure and store each linked list structure in an array if possible. If not possible, what is a possible alternative?
It is entirely possible to store an array of LinkedLists; arrays can be applied to objects as well as primitive types. However, I would advise creating a Matrix class, because square matrices are not linked lists; they have data in two dimensions, not just one. At the very least, you could use a two-dimensional array of floats to represent a matrix, and store a LinkedList of double[][]s. The closer your representation is to the actual object, the easier it will be for you.
If you are allowed to use the standard LinkedList class what java already has, the here is a possible implementation of reading, and storing your matrices:
int size = 10; //width and height of your matrix.
LinkedList<LinkedList<Integer>> matrix = new LinkedList<LinkedList<Integer>>();
for (int i = 0; i<size; i++)
{
LinkedList<Integer> list = new LinkedList<Integer>();
for (int j = 0; j < size; j++)
{
//read the actual item
}
matrix.add(list);
}
For reading a matrix (probably numbers) i advise to use the class called Scanner. You can create a new Scanner, what will be able to read your file, number by number:
Scanner sc = new Scanner(new File("input.txt"));
And you can read integer values with it, without any conversion like this:
int x = sc.nextInt();
You can make an array of linked lists in Java by declaring LinkedList[], but if you do, your performance will suffer badly. A look at matrix multiplication will illustrate the reason.
If A and B are matrices where the A's column count equals B's row count, then A * B[r, c] is the dot product of row r in A with column c in B. This means we have to extract rows and columns from our matrices.
If we form matrices from lists (of any sort), we can store them row-wise (i.e., where the 0-th list represents row 0), or column-wise (where the 0-th list represents column 0).
Now we run into a problem. In a linked list, the method get(n) starts at the beginning of the list and finds the next member n times -- which makes it run in order n time. A matrix built from linked lists will either extract columns very slowly (if stored row-wise), or extract rows very slowly (if stored column-wise).
I's suggest keeping it simple by using arrays of arrays. You can allocate an n x n array with
int[][] values = new int[n][n];
The value 'n' must be defined, of course.
Hope that this helps.

In java to remove an element in an array can you set it to null?

I am trying to make a remove method that works on an array implementation of a list.
Can I set the the duplicate element to null to remove it? Assuming that the list is in order.
ArrayList a = new ArrayList[];
public void removeduplicates(){
for(a[i].equals(a[i+1]){
a[i+1] = null;
}
a[i+1] = a[i];
}
No you can't remove an element from an array, as in making it shorter. Java arrays are fixed-size. You need to use an ArrayList for that.
If you set an element to null, the array will still have the same size, but with a null reference at that point.
// Let's say a = [0,1,2,3,4] (Integer[])
a[2] = null;
// Now a = [0,1,null,3,4]
Yes, you can set elements in an array to null, but code like a[i].equals(a[i+1]) will fail with a NullPointerException if the array contains nulls, so you just have to be more careful if you know that your array may contain nulls. It also doesn't change the size of the array so you will be wasting memory if you remove large numbers of elements. Fixed size arrays are generally not a good way to store data if you are often adding and removing elements - as you can guess from their name.
Can I set the the duplicate element to null to remove it?
You can set an element of the array null but this doesn't remove the element of the array... it just set the element to null (I feel like repeating the first sentence).
You should return a cleaned copy of the array instead. One way to do this would be to use an intermediary java.util.Set:
String[] data = {"A", "C", "B", "D", "A", "B", "E", "D", "B", "C"};
// Convert to a list to create a Set object
List<String> list = Arrays.asList(data);
Set<String> set = new HashSet<String>(list);
// Create an array to convert the Set back to array.
String[] result = new String[set.size()];
set.toArray(result);
Or maybe just use a java.util.Set :)
Is this a homework question?
Your problem is analogous to the stream processing program uniq: Preserve -- by way of copying -- any element that doesn't match the one before it. It only removes all duplicates if the sequence is sorted. Otherwise, it only removes contiguous duplicates. That means you need to buffer at most one element (even if by reference) to use as a comparison predicate when deciding whether to keep an element occurring later in the sequence.
The only special case is the first element. As it should never match any preceding element, you can try to initialize your buffered "previous" element to some value that's out of the domain of the sequence type, or you can special-case your iteration with a "first element" flag or explicitly copy the first element outside the iteration -- minding the case where the sequence is empty, too.
Note that I did not propose you provide this operation as a destructive in-place algorithm. That would only be appropriate with a structure like a linked list with constant-time overhead for removing an element. As others note here, removing an element from an array or vector involves shuffling down successor elements to "fill the hole", which is of time complexity n in the number of successors.
The straight-forward answer to your question is that setting an array or ArrayList element to null gives you a null entry in the array or ArrayList. This is not the same thing as removing the element. If just means that a[i] or a.get(i) will return null rather than the original element.
The code in the question is garbled. If you are going to use an ArrayList, the simplisitic solution would be something like this:
ArrayList a = new ArrayList();
public void removeduplicates() {
for (int i = 0; i < a.size() - 1; ) {
if (a.get(i).equals(a.get(i + 1)) {
a.remove(i);
} else {
i++;
}
}
}
but in the worst case, that is O(N**2) because each call to remove copies all elements at indexes greater than the current value of i.
If you want to improve the performance, do something like this:
public ArrayList removeduplicates() {
ArrayList res = new ArrayList(a.size());
if (a.size() == 0) {
return res;
}
res.add(a.get(0));
for (int i = 1; i < a.size(); i++) {
if (!a.get(i - 1).equals(a.get(i)) {
res.add(a.get(i));
}
}
return res;
}
(This is a quick hack. I'm sure it could be tidied up.)
Your code example was quite confusing. With ArrayList[] you showed an array of ArrayList objects.
Assuming that you're talking about just the java.util.ArrayList, then the most easy way to get rid of duplicates is to use a java.util.Set instead, as mentioned by others. If you really want to have, startwith, or end up with a List for some reasons then do:
List withDuplicates = new ArrayList() {{ add("foo"); add("bar"); add("waa"); add("foo"); add("bar"); }}; // Would rather have used Arrays#asList() here, but OK.
List withoutDuplicates = new ArrayList(new LinkedHashSet(withDuplicates));
System.out.println(withoutDuplicates); // [foo, bar, waa]
The LinkedHashSet is chosen here because it maintains the ordering. If you don't worry about the ordering, a HashSet is faster. But if you actually want to have it sorted, a TreeSet may be more of value.
On the other hand, if you're talking about a real array and you want to filter duplicates out of this without help of the (great) Collections framework, then you'd need to create another array and add items one by one to it while you check if the array doesn't already contain the to-be-added item. Here's a basic example (without help of Arrays.sort() and Arrays.binarySearch() which would have eased the task more, but then you would end up with a sorted array):
String[] array1 = new String[] {"foo", "bar", "foo", "waa", "bar"};
String[] array2 = new String[0];
loop:for (String array1item : array1) {
for (String array2item : array2) {
if (array1item.equals(array2item)) {
continue loop;
}
}
int length = array2.length;
String[] temp = new String[length + 1];
System.arraycopy(array2, 0, temp, 0, length);
array2 = temp;
array2[length] = array1item;
}
System.out.println(Arrays.toString(array2)); // [foo, bar, waa]
Hope this gives new insights.
If you are implementing your own list and you have decide to use a basic primitives storage mechanism. So using an array (rather than an arraylist) could be where you start.
For a simple implementation, your strategy should consider the following.
Decide how to expand your list. You could instantiate data blocks of 200 cells at a time. You would only use 199 because you might want to use the last cell to store the next allocation block.
Such linked list are horrible so you might decide to use a master block to store all the instances of blocks. You instantiate a master block of size 100. You start with one data block of 200 and store its ref in master[0]. As the list grows in size, you progressively store the ref of each new data blocks in master[1] .... master[99] and then you might have to recreate the master list to store 200 references.
For the reason of efficiency, when you delete a cell, you should not actually exterminate it immediately. You let it hang around until enough deletion has occurred for you to recreate the block.
You need to somehow flag a cell has been deleted. So the answer is obvious, of course you can set it to null because you are the king, the emperor, the dictator who decides how a cell is flagged as deleted. Using a null is a great and usual way. If you use null, then you have to disallow nulls from being inserted as data into your list class. You would have to throw an exception when such an attempt is made.
You have to design and write a garbage collection routine and strategy to compact the list by recreating blocks to remove nullified cells en mass. The JVM would not know those are "deleted" data.
You need a register to count the number of deletions and if that threshold is crossed, garbage collection would kick in. Or you have the programmer decide to invoke a compact() method. Because if deletions are sparse and distributed across various data blocks, might as well leave the null/deleted cells hang around. You could only merge adjacent blocks and only if the sum of holes in both blocks count up to 200, obviously.
Perhaps, when data is appended to a list, you deliberately leave null holes in between the data. It's like driving down the street and you see house addresses incremented by ten because the the city has decided that if people wish to build new houses in between existing houses. In that way you don't have to recreate and split a block every time an insertion occurs.
Therefore, the answer is obvious to yourself, of course you can write null to signify a cell is deleted, because it is your strategy in managing the list class.
No, an array element containing a null is still there, it just doesn't contain any useful value.
You could try moving every element from further down in the list up by 1 element to fill the gap, then you have a gap at the end of the array - the array will not shrink from doing this!
If you're doing this a lot, you can use System.arraycopy() to do this packing operation quickly.
Use ArrayList.remove(int index).
if(a[i].equals(foo()))
a.remove(i)
But be careful when using for-loops and removing objects in arrays.
http://java.sun.com/j2se/1.3/docs/api/java/util/ArrayList.html

Categories

Resources