We are about to switch to a new forum software. Until then we have removed the registration on this forum.
int [][] GRE = new int[GREsize][GREsize]; // GREsize = 5
at a certain moment in the program GREsize becomes 6 so the array shroud expand to accommodate the new values.
GRE = append(GRE,6,6); // does not work.
Will the suggested code also works with expand() and shorten() ?
Thanks
Answers
Append, shorten and expand only work with a 1D array. In your example you have 5 1D arrays, in an array. So you gotta get all of those arrays separately and call those functions.
http://forum.Processing.org/two/discussion/8045/how-to-format-code-and-text
For most cases, when some array's dimension isn't of a fixed length, we're better off replacing it w/ a dynamically-sized List instead: https://Processing.org/reference/ArrayList.html
For your particular case, an IntList is the most fit: https://Processing.org/reference/IntList.html
However, when that re-dimension just happens sporadically, we can still decide to keep on using a regular array and rely on append(), expand() and shorten() in order to achieve dynamic length too.
I've come up w/ expandGrid() as an enhanced expand()'s replacement for 2D arrays: :ar!
The 'colouredmirrorball' is definitely an elegant solution but I have no idea how to separate the int [][] array in int [] row's and int [] col's to call the function and then join them again to an int [][] array . Anyway thanks for your help.
I dunno why you'd think so since in expandGrid(int[][] grid, int dim) we gotta pass the whole 2D array:
grid = expandGrid(grid, grid.length + 1);
new
array w/ the same content but diff. length.append(i, 6);
doesn't have any effect at all w/o assigning it to some variable![]
operator.for ( : )
loop likefor(int[] i : GRE)
doesn't work for it either.new
"row" of "cols" and assign it back to the newly expanded outer index.Thanks for your comment. does grid = expandGrid(grid, grid.length - 1); also shorten the array?
Indeed it does. sorry for my hasty reaction. I will implement your code tomorrow. it's midnight now.
Indeed it does! But it's buggy the way it was implemented; since I wasn't thinking about that option! 8-|
The last outer row index is always replaced by a
new int[dim]
array! :-&In order to fix that, we need an
if ()
to check whether the desired dim is indeed>
current length before proceeding w/ thegrid[dim - 1] = new int[dim];
:Leaving the buggy original implementation here for "historical" reasons: :-j
Yup, sorry, typed it on my phone during a boring lecture, without a chance to test it. Though, maybe, this works?
Unfortunately not! It "violates" these 2 issues I've mentioned before: :-<
[]
operator.for ( : )
loop likefor(int[] i : GRE)
doesn't work for it either.@
i = append(i, 6);
you're merely reassigning another array w/ new element6
to the iterator i.In short, just making iterator i point to another array rather than the actual 1 it got from GRE.
You're not putting the append()'s
new
array back to the original array GRE's outer dimension at all!Actually, we shouldn't reassign iterators ever! Placing a
final
in it would safe-guard us against it:for (final int[] i : GRE) i = append(i, 6); // it won't compile due to iterator's reassignment!
Try out this mini sample below and see that
println(grid[0].length);
finally displays4
only after the regularfor ( ; ; )
loop: :>P.S.: Be aware that append() merely adds 1 new element to an array's dimension:
https://Processing.org/reference/append_.html
So it can only increment its length 1 by 1.
We can only specify the exact length we want w/ expand() though: L-)
https://Processing.org/reference/expand_.html
I must admit this topic interested me and in particular creating a single function that can resize a 2D array (expand or contract or both) and for both square and oblong arrays. So I came up with this example
If you run it you get the following output
It is also possible to expand one dimension and contract the other dimension at the same time.
P.S.: Another issue I've realized just now:
int[][]
2D array.new
clone() of the passed array.The OP asks
so we need a solution that does both.
Thanks a lot! I have now two perfectly working solutions. Unfortunately I am not in a position to make an assessment of the quality of the code. It works and I realize that writing code is not an exact science.
new
array for all cases.P.S.: Version 3.3 available now: Got rid of
final int len = min(grid.length, rows);
:>P.S.: Another v3.4: Got rid of
if (grid == null) return null;
.Now in case passed parameter grid is
null
, instead it returns anew int[rows][cols]
2D array w/ specified rows x cols dimensions! \m/I disagree, although software quality is a huge topic in itself even novices can have an opinion.
Look at the solutions on offer, which one makes the most 'sense' to you, which one looks 'cleaner', which one does everything you might want, either now or in the future e.g. contract as well as expand, cope with 'oblong' arrays.
@GoToLoop
What is the problem with that? Don't forget
arrayCopy
is a Processing function the same wayexpand
is so calling either is just as valid.It is your assumption that the function should always return a new array and is no more valid than any other assumption. There is no software engineering reason why the the function shouldn't return the unchanged array.
rows = abs(rows);
cols = abs(cols);
I don't agree with this code because it will end up changing the array even when illegal negative values are entered. Invalid data should be reported or ignored it should not be used to modify valid data.
I guess only you can reply that! B/c I utterly fail to see where have you found any "negativity" about listing characteristics of your implementation! @-)
Since it's made from scratch, obviously it is faster than mine which relies on Processing's API! ~:>
Processing's arrayCopy() is merely a wrapper for Java's System.arraycopy() after all:
http://docs.Oracle.com/javase/8/docs/api/java/lang/System.html#arraycopy-java.lang.Object-int-java.lang.Object-int-int-
Although Processing's expand() calls that as well. But only after instantiating a
new
1D array. >-)Now I have looked again neither can I oops! :\">
Now that's where my critique had started, not before! L-)
And seems like you refuse to accept that behavior is very bug prone! [-(
I believe you agree that your resizeArray() returns a distinct
int[][]
array w/ the contents of the passedint[][]
array, right?However, if we blindly "trust" your implementation, we may end up w/ a nasty, hard-to-find bug: ~X(
Looks like we both made some assumptions based on our own personal interpretation of the OPs requirements.
My premises were
1) A copy of the original array was not required because the resized array would be used in instead.
2) A new array would only be needed if the array size actually changed.
3) Requests to resize the array using dimension sizes <=0 would be ignored and the original array would continue to be used.
4) The resize operation could be used to enlarge or reduce the array size
5) As much or the original data should be retained.
The 'bug' you reported in the last post was in fact a logical error because your premises were not the same as mine. My fault really I should have documented the resize function to say what it did.
So for the sake of completeness and to clarify my code I have documented the sketch and the function clearly stating the programs functionality. Note that I have NOT changed the resize function code rather I have documented it.
The output of this sketch is
true - that's why we should document code - to explain the API :)
Take notice that by merely deleting:
if (size0 <= 0 || size1 <= 0 || asize0 == size0 && asize1 == size1) return a;
resizeArray() would pass my edgy case test above just like expand2D()! *-:)
Besides simplifying a lot its API documentation. :-bd
if (size0 <= 0 || size1 <= 0) return a;
This would then pass your test case because It would mean that it would duplicate the array even if it is the same size. I could live with that. :)
It is still necessary to handle requests for invalid dimension sizes i.e. <= 0
Your solution of taking the absolute values of the sizes is not something I would do for the reasons I gave earlier.
The only acceptable options would be to have my function return either
null
or the original array. The disadvantage ofnull
is that the user would have to test the returned value every time this method is called. Returning the original array still allows the user to test if the array has changed but it is now optional.Java arrays already check for that. Following statement would fail outright: :>
int [][] b = new int [size0][size1];
Examples where programmers take a more strict approach or tries to reasonably guess/assume what the passed arguments meant are plenty to find.
Even in Processing's API we can find the usage of abs() to deal w/ nonsensical negative values:
ellipse(width>>1, height>>1, -width*.75, -height*.75);
Every1 knows dimensions can't be negative the same way that array indices can't either! >-)
Also, pixels can't have fractional values. But round() is silently used on "drawing" APIs. :(|)
Even in our own browsers, we don't type in
http://
or evenwww.
anymore.But they're silently & internally "corrected" nonetheless. :P
My own expand2D() can't
return
anull
value in any circumstance.In summary, it's effectively a
@NotNull
return method. \m/However, your resizeArray() has a case where it indeed returns
null
:It happens when we pass a
null int[][]
argument! 3:-OIn summary resizeArray() has 3 types of
return
:new int[][]
array.int[][]
passed array.null
.Among those 3 above, #2 is the nastier to hunt down when debugging.
That's what I've been trying to warn since the beginning!
The 3rd
null
case is the most common in Java and many other languages.Any
@Nullable
return method (absolute majority btW) demands anull
check in most cases anyways.Therefore I don't see why checking for
null
would be problematic since it's expected in many places after all.I disagree! Majority of folks wouldn't know and/or remember that a method which is supposed to return a distinct object can in some "rare" (invalid arguments) cases return the same object!
It's not in the same league as testing for
null
. Which is a very common case in programming! ~O)Just take a look at my test case. If I didn't comment "bug is here", that statement would look completely "innocent" for any1 debugging the code: >:)
int[][] supposedClone = resizeArray(gre, 2, 1); // I'm innocent! Bug isn't here!!!
It is likely that the new array sizes are calculated at runtime rather than hardcoded in the source code. If the sizes are <=0 then there is a problem. We could handle that problem ourselves so the program continues rather than allow the JRE to bring our program to a halt, both are valid choices provided we make the user aware of the one we chose.
If the calculated size is [2][-3] then to assume that the user is happy, and that the program will function as expected with an array [2][3] is presumptuous.
The key word there is reasonably I don't think converting [2][-3] to [2][3] is reasonable because there is nothing to support that decision, there is no logic to it. In fact it is purely an arbitrary decision on your part. If programmers do apply constraints to the method parameters then they should document it.
Not true the function would fail at the first line because it doesn't test for null parameters. But if the user did pass null and the program crashed it is NOT a software bug it is because the user did not honour the contract specified in the function documentation. It quite clearly states that the method expects an array with minimum size [1][1]
I wouldn't expect them to remember any more than I remember all the Java or Processing methods I have ever used that's why we have Javadocs and references. I would look at the API documents to find out what parameters and limits apply. Again wrong it quite clearly states that the method expects an array with minimum size.
Two more points on this bit
1) It is quite clear in the function documents that the method does not always return a new array.
2) If the dimensions are calculated then invalid sizes might not be as rare as you expect. It depends on the code that calls this method.
I think we will have to agree to disagree on this. :)