How to remove specific items form an 2D Array?

edited January 2017 in Programming Questions

I'm trying to write a class that contains a 2D array of coordinates. In order to make the function that removes some element specified by its location in the array, i need a function that pops or splices. For 1D arrays I would rather choose for the subset() or arraycopy() function, such as:

EndofNewArrayX = subset(CoordinatesX, Pixel); BeginofNewArrayX = subset(CoordinatesX, 0, Pixel-1); NewArrayX = concat(BeginofNewArrayX, EndofNewArrayX);

in which pixel defines the place that needs to be removed.

How can I accomplish this in an 2D array, where the first dimension is targeted to be removed:

int [][]Coordinates = {{5,10}, {6,11}, {14,3},{24,8},{14,10}};

should become for example:

int [][]Coordinates = {{5,10}, {6,11},{24,8},{14,10}};

Would be great if anybody could get me in the right direction.

Answers

  • edited January 2017
    // https://forum.Processing.org/two/discussion/20352/
    // how-to-remove-specific-items-form-an-2d-array#Item_1
    
    // GoToLoop (2017-Jan-19)
    
    static final int IDX_TO_REMOVE = 2;
    int[][] coords = { {5, 10}, {6, 11}, {14, 3}, {24, 8}, {14, 10} };
    
    void setup() {
      println("Original 2D Array[][]:");
      printIntArr2d(coords);
    
      coords = delIdxIntArr2d(IDX_TO_REMOVE, coords);
    
      println("\nShortened 2D Array[][]:");
      printIntArr2d(coords);
    
      exit();
    }
    
    @SafeVarargs static final int[][] delIdxIntArr2d(final int idx, final int[]... arr2d) {
      final Object endSplitArr = subset(arr2d, idx+1);
      return (int[][]) concat(subset(arr2d, 0, idx), endSplitArr);
    }
    
    @SafeVarargs static final void printIntArr2d(final int[]... arr2d) {
      int idx = 0;
      for (final int[] arr1d : arr2d) {
        println(idx++);
        println(arr1d);
      }
    }
    
  • Answer ✓

    This is a terrible idea. Arrays were never designed for this. ArrayLists would be a better choice.

  • edited January 2017

    Thank you both for the fast answers, I think koogs is absolutely right and ArrayList would offer a tremendous safe in code lines. I just was not aware of this type of structure and should start thinking more in classes. In this case Pixel.remove(i) is sufficient already. Also, the possiblity of using ArrayLists offers synchronization of threads as well. I learned a lot, thanks for the input!

  • edited January 2017

    In this case Pixel.remove(i);

    In Java (and also JS), variables & functions follow the lowerCaseCamel naming convention.
    UpperCaseCamel is reserved for classes & interfaces only. ~O)

    Also, the possibility of using ArrayLists offers synchronization of threads as well.

    Class ArrayList isn't synchronized at all: b-(
    http://docs.Oracle.com/javase/8/docs/api/java/util/ArrayList.html

    For that, you can pick Collections.synchronizedList() in order to wrap it under:
    http://docs.Oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-

    Class CopyOnWriteArrayList:
    http://docs.Oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

    Or even the old deprecated class Vector:
    http://docs.Oracle.com/javase/8/docs/api/java/util/Vector.html

  • edited January 2017

    and ArrayList would offer a tremendous safe in code lines.

    As a replacement for int[][], I'd suggest ArrayList<int[]>: O:-)

    import java.util.List;
    final List<int[]> coords = new ArrayList<int[]>();
    

    But if you prefer that even the inner dimension not to be an array either, how about IntList in place of that generic int[]?: :\">

    import java.util.List;
    final List<IntList> coords = new ArrayList<IntList>();
    

    https://Processing.org/reference/IntList.html

    And although not int type, class PVector is a good fit somehow; given you only need 2 values for the internal dimension: :ar!

    import java.util.List;
    final List<PVector> coords = new ArrayList<PVector>();
    

    https://Processing.org/reference/PVector.html

  • edited January 2017

    @Melanie --

    I'm trying to write a class that contains a 2D array of coordinates

    I would also vote for using an ArrayList of PVectors, as per @GoToLoop 's last suggestion. Unless you have specific performance requirements then this will be very easy to read and understand.

    ArrayList<PVector> coords = new ArrayList<PVector>();
    // add a point
    coords.add(new PVector(120,380));
    // access a point
    println( coords.get(0).x, coords.get(0).y );
    // remove a point
    coords.remove(0);
    

    An aside: I'm not sure what you are using these coordinates for, but here is one example use: Because PShape is backed by an immutable array of vertices it is sometimes useful to create a mutable PShape wrapper class using this kind of coordinate ArrayList, then replace the wrapped PShape with a brand new one any time the vertex ArrayList updates (importing the changed ArrayList into the write-once vertices of the new replacement shape).

  • edited January 2017

    Thank you all for thinking along!

    @GoToLoop when I mentioned synchronization of ArrayLists, I was refering to the possiblity of using Collections.synchronizedList(). However, I just learned about the concept and do now understand that this function can be used for every List and that PVector indeed has internal synchronization. Good to know, thanks!

    Basically, I need to destinguish the distance of some cells in an image. Therefore I save high intensity pixels of an image in a list as part of the object Cell. With those pixels I want to:

    • calculate the distance of one cell to another cell
    • easily remove or add pixels based on their value or location

    Therefore, I should have easy acces to the pixels:

    • coordinates
    • location when PImage is loaded (loc = x + y * width)
    • value

    Concluding, if I understand correctly:

    • @jeremydouglass If I use ArrayList< PVector >, I should always look up their value in the PImage before running a statement, although this allows easy determination of their distances.
    • ArrayList< IntList > offers the possiblity of removing and adding items in between the list easily
    • ArrayList< Object > is just as sufficient as IntList but offers the possiblity to also calculate the loc internally: just a little more smooth.

    I think I'll go for the ArrayList type, thanks for clearing up the different List options!

  • edited January 2017 Answer ✓

    and that PVector indeed has internal synchronization.

    Processing's PVector class got no synchronization at all.
    And got nothing to do w/ Java's Vector class either: [-X

    1. https://Processing.org/reference/PVector.html
    2. http://docs.Oracle.com/javase/8/docs/api/java/util/Vector.html
  • edited January 2017

    ArrayList is just as sufficient as IntList but offers the possibility to also calculate the loc internally: just a little more smoothly.

    • Class IntList is very close to an ArrayList<Integer>.
    • Both classes got an internal regular array.
    • And both got a method called get() in order to access an indexed value from it.
    • Therefore, index calculation is exactly the same for both containers. ;;)
    1. https://Processing.org/reference/IntList_get_.html
    2. http://docs.Oracle.com/javase/8/docs/api/java/util/List.html#get-int-
  • Oh this doesn't work out too nice, I'm sorry. My < Object > and < IntList > dissapeared, since I didnt not use the space in the comment above...

    What I meant was the difference between ArrayList < IntList > and ArrayList < Object > Thus, with ArrayList < Object > I could add the loc = x * y * width once within the class and not during every new ArrayList < IntList > item. Right?

  • edited January 2017

    Just some an alternative approach. How about a class to represent those coords and their corresponding converted index? :D

    Later, you can place them in an ArrayList container. Check it out below: O:-)

    /**
     * Image Indexed Coords (v1.0)
     * GoToLoop (2017-Jan-26)
     *
     * forum.processing.org/two/discussion/20352/
     * how-to-remove-specific-items-form-an-2d-array#Item_11
     */
    
    void setup() {
      IdxPixCoord coord = new IdxPixCoord(width).clone();
      coord.setXY(20, 10);
      exit();
    }
    
    static class IdxPixCoord implements Cloneable {
      int x, y, w, idx;
    
      IdxPixCoord(final PImage img) {
        updateWidth(img);
      }
    
      IdxPixCoord(final int w) {
        setWidth(w);
      }
    
      IdxPixCoord(final int x, final int y, final PImage img) {
        this(x, y, img.width);
      }
    
      IdxPixCoord(final int x, final int y, final int w) {
        setXY(x, y).setWidth(w).updateIndex();
      }
    
      IdxPixCoord setXY(final int px, final int py) {
        x = px;
        y = py;
        return this;
      }
    
      IdxPixCoord setWidth(final int pw) {
        w = pw;
        return this;
      }
    
      IdxPixCoord setIndex(final int ind) {
        idx = ind;
        return this;
      }
    
      IdxPixCoord updateXY() {
        x = idx % w;
        y = idx / w;
        return this;
      }
    
      int updateWidth(final PImage img) {
        return setWidth(img.width).w;
      }
    
      int updateIndex() {
        return idx = y*w + x;
      }
    
      @ Override int hashCode() {
        return w << 22 | (y & 0x7ff) << 11 | x & 0x7ff;
      }
    
      @ Override boolean equals(Object other) {
        if (other == this)  return true;
        if (!(other instanceof IdxPixCoord))  return false;
        final IdxPixCoord o = (IdxPixCoord) other;
        return o.x == x & o.y == y & o.w == w;
      }
    
      @ Override IdxPixCoord clone() {
        try {
          return (IdxPixCoord) super.clone();
        }
        catch (CloneNotSupportedException ex) {
          throw new RuntimeException(ex);
        }
      }
    
      @ Override String toString() {
        return "x: " + x + ", y: " + y + ", w: " + w + ", idx: " + idx;
      }
    }
    
Sign In or Register to comment.