How do i copy out one row of a 2d array into a 1d array?

what is the proper syntax for copying one row of a 2d array of integers into an existing 1d array? like if i have:

 int[][] stuff = {{1,2,3},{4,5,6},{7,8,9}};  

and i also have:

 int[] usethis = {0,0,0};  

and i want to copy one row of 'stuff' into 'usethis'.

logically it should be possible to do something like:

 usethis = new int[] {4,5,6};  

only copying it out of 'stuff', e.g.

 usethis = new int[] stuff[2];  

only that doesn't seem to work.

and i do NOT want to have to loop thru it element by element. that would be entirely too stupid. is there a way?

Answers

  • What exactly do you mean when you say it doesn't seem to work? What happens instead?

    Why don't you want to loop through each element?

    Can you post an MCVE that demonstrates exactly what you're trying to do?

  • You can point your array at an index of your 2D array:

    int[][] stuff = {{1,2,3},{4,5,6},{7,8,9}};
    int[] myArray = stuff[2];
    

    However, this isn't really copying the array. Changes to one array will affect the other. In order to actually copy the array, you'll have to loop through the elements. You might be able to use the Arrays class if you're in Java mode, but that's just looping over them for you.

  • edited August 2015

    are you saying that copying that one row out of 'stuff' will change 'stuff'? anyway your suggestion appears to work just fine. what i was reading in the array documentation seemed to indicate that i had to declare a NEW array to change an existing array, and it was apparently that 'new' statement that was messing things up.

  • edited August 2015

    http://forum.Processing.org/two/discussion/8045/how-to-format-code-and-text

    int[][] stuff = {{1,2,3}, {4,5,6}, {7,8,9}};
    
    int[] myArray = stuff[2]; // it's an alias for stuff[2].
    myArray[0] = 10; // thus it alters stuff[2] too!
    println(stuff[2][0]); // prints out 10. stuff[2] is also affected!
    
    int[] myClone = stuff[2].clone(); // it's a clone for stuff[2].
    myClone[0] = 20; // thus it's independent from stuff[2]!
    println(stuff[2][0]); // still prints out previous 10. stuff[2] isn't affected!
    
    exit();
    
  • edited August 2015

    weird. why would anyone want to set things up that way? a copy should be a copy, not an alias. seems like it would make a lot more trouble than it would save.

  • edited August 2015 Answer ✓

    W/o aliasing object references, we couldn't be able to pass them into methods.
    Since parameters are local variables too that should point to the object reference as well.
    If we need a shallow clone() of it, we gotta be explicit about it! :-B

  • edited August 2015

    And just for completeness' sake, here's how to fully clone() a 2D array: :ar!

    int[][] stuff = {{1,2,3}, {4,5,6}, {7,8,9}};
    for (int[] thing : stuff)  println(thing);
    println();
    
    int[][] myClone = stuff.clone(); // Cloning the outer dimension of the 2D array.
    for (int[] clone : myClone)  println(clone);
    
    myClone[0][0] = 100;
    print('\n', stuff[0][0]); // Prints out 100. It's still not a real clone!
    
    // In order to fix that, we gotta clone() each of its inner arrays too:
    for (int i = 0; i != myClone.length; myClone[i] = stuff[i++].clone());
    
    myClone[0][0] = 200;
    println('\n', stuff[0][0]); // Still prints out previous 100 and not 200.
    // It's a full clone now and not a mere reference alias!
    
    exit();
    
  • what is arraycopy?

    This is a very fast array copying function. Instead of copying element by element the JVM simply copies one area of RAM (from inside the source array) to another area of RAM (destination array)

  • i have read that clone is best avoided as it is tricky and really only applies to arrays of objects. is that true?
    and im wondering if arraycopy makes a true copy or is this also just an alias that will affect the source?
    and why is there nothing about that issue in the array documentation?

  • edited August 2015

    ... it is tricky and really only applies to arrays of objects.

    I'm pretty sure that int[] is an array of primitive ints, right?! :-@
    About being tricky, it's when we implement clone() for our own classes.
    Array's clone() is already implemented by the Java's devs. It's safe & fast!

    And I'm wondering if arraycopy() makes a true copy or...

    As already mentioned by other answerers, instead of clone() we can use new + arrayCopy():
    https://processing.org/reference/arrayCopy_.html

    But of course it's gonna be more convoluted than my clone() version.
    And I bet even a bit slower! 3:-O

    As an exercise, try to convert the clone() example to use new int[] + arrayCopy() instead. ~O)

  • edited August 2015

    are you saying that copying that one row out of 'stuff' will change 'stuff'?

    The actual copying doesn't change anything. But note that if you make a change to myArray, you'll make a change to the original stuff array as well.

    void setup(){
    
        int[][] stuff = {{1,2,3},{4,5,6},{7,8,9}};
        int[] myArray = stuff[2]; 
    
        //this changes myArray[0], which is stuff[2], so it changes stuff[2][0]
        myArray[0] = 100;
    
        println(stuff[2][0]);
    
    }
    

    This might not matter, but your original question was about copying an array, which this isn't.

    what i was reading in the array documentation seemed to indicate that i had to declare a NEW array to change an existing array

    That doesn't make much sense. You either need to declare a new array and then copy elements into it, or you can just point to an existing array. Declaring a new array has no effect on an existing array.

    weird. why would anyone want to set things up that way? a copy should be a copy, not an alias. seems like it would make a lot more trouble than it would save.

    Because a copy and an alias are two different tools used for two different jobs. For example, you might have an array that contains huge Strings, and maybe a function that prints that array. You wouldn't want to have to copy that entire array every time you printed it, otherwise you'd run out of memory.

    i have read that clone is best avoided as it is tricky and really only applies to arrays of objects. is that true?

    Yes. Clone is broken. Don't use it. Recommended reading list:

    http://www.artima.com/intv/bloch13.html

    http://stackoverflow.com/questions/2427883/clone-vs-copy-constructor-which-is-recommended-in-java

    http://stackoverflow.com/questions/18240037/why-object-clone-method-available-only-to-classes-that-implement-cloneable-int

    and im wondering if arraycopy makes a true copy or is this also just an alias that will affect the source?

    Don't be afraid to write some code that answers these questions for you!

    and why is there nothing about that issue in the array documentation?

    Because Processing tries to keep things as simple as possible. That being said, Processing does offer several functions related to array manipulation. Check out the "Array Functions" section of the reference: https://www.processing.org/reference/

    Also note that Processing has its own arrayCopy() function: https://www.processing.org/reference/arrayCopy_.html

  • edited August 2015

    And why is there nothing about that issue in the array documentation?

    IMO, Processing's documentation is pretty below my expectations. Fulla errors & omissions! 8-|
    Looking at array's reference here: https://processing.org/reference/Array.html

    They don't mention anything about multidimensional arrays at all!
    Much less that clone() is available for arrays! X(

    Actually all object types got clone() method. Since it belongs to class Object:
    http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone--

    And most of us already know that all classes in Java extends Object too, right? ;;)
    Problem is implementing clone() by ourselves. A lil' convoluted and almost always unnecessary. ~O)

  • im wondering if arraycopy makes a true copy or is this also just an alias that will affect the source?

    arraycopy calls System.arraycopy. The Java docs the explains this method in great detail.

  • edited August 2015

    Processing's documentation is purposely simplified. If you want more involved documentation, then go to Java's API.

    That being said...

    https://processing.org/tutorials/2darray/

    https://processing.org/examples/array2d.html

  • i've read the tutorials and examples and nowhere is there the slightest mention that the copy actually is an alias that allows the original material to be changed when the copy is changed. this strikes me as an important issue that ought to be explicitly addressed, possibly in very large type, not hidden in a footnote somewhere.

  • In Java arrays are objects so your original variables usethis and stuff[2] are in fact object references so in the statement
    usethis = stuff[2];
    you are copying object references so now both usethis and stuff[2] reference the same array, so changing one changes the other.

    This is the solution to your original post

    int[][] stuff = {{1,2,3},{4,5,6},{7,8,9}};  
    int[] usethis = {0,0,0};  
    
    arraycopy(stuff[2], 0, usethis, 0, 3);
    
    // Prove that changing the source does not 
    // change the copy
    stuff[2][0] = -9;
    println(stuff[2]);
    println(usethis);
    

    note that there is no iteration :)

  • edited August 2015

    I was pretty aware that clone() had some design problems a long time already!
    However, I was ALSO aware that cases where it "might" be problematic are solely related to inheritance!

    According to the 1st link @KevinWorkman posted as "proof" of clone()'s dangers:
    http://www.Artima.com/intv/bloch13.html

    We can read this very important "revealing" excerpt:

    He told me that he doesn't use clone anymore except to copy arrays.
    You should use clone to copy arrays, because that's generally the fastest way to do it.

    Now even though I've presented 2 working examples relying on clone() approach to copy arrays,
    other answerers insist on frightening the OP it's "dangerously" broken!!! @-)
    Although it's perfectly right! And indeed faster and less complicated than arrayCopy() approach! 8-}

    And about implementing clone() for our own classes, another excerpt from that same article:

    I often provide a public clone method on concrete classes because people expect it.

    If a pro developer provides clone() implementations for his own libraries, it's assumed it's working!
    Only catch is that clone() is limited to actual implementation classes and not interfaces and abstract 1s!

    Hope it's enough to clear things out for every1! *-:)

  • Josh Bloch says clone is broken, so I'm going to listen to him. When you design half of Java and publish a couple dozen books on it, I'll listen to you instead. :p

  • i've read the tutorials and examples and nowhere is there the slightest mention that the copy actually is an alias that allows the original material to be changed when the copy is changed. this strikes me as an important issue that ought to be explicitly addressed, possibly in very large type, not hidden in a footnote somewhere.

    Look at this line:

    int[][] stuff = {{1,2,3},{4,5,6},{7,8,9}};
    int[] myArray = stuff[2]; 
    

    You aren't copying anything here. You are simply referencing stuff[2] by pointing myArray at it. Nothing has been copied.

    This is not limited to arrays. This is the basics of how Java works. Consider a different example:

    PVector vectorA = new PVector(100, 100);
    PVector vectorB = new PVector(200, 200);
    
    PVector[] vectors = {vectorA, vectorB};
    
    PVector vectorC = vectors[0];
    vectorC.x = -500;
    
    println(vectorA.x); //what should this print?
    

    Answer that question, and then run this code to check whether you're correct.

    I also highly recommend reading these two articles:

    http://www.javaranch.com/campfire/StoryCups.jsp

    http://www.javaranch.com/campfire/StoryPassBy.jsp

    In other words, nothing is missing from the array documentation because this has very little to do with arrays specifically. This is simply how Java (and therefore Processing) works.

Sign In or Register to comment.