Как убрать строку в двумерном массиве - PullRequest
5 голосов
/ 26 ноября 2009

У меня есть простой массив, вроде как

1 2 3 4 5 6 7 8 9
6 2 7 2 9 6 8 10 5
2 6 4 7 8 4 3 2 5
9 8 7 5 9 7 4 1 10
5 3 6 8 2 7 3 7 2

Итак, давайте назовем это matrix[5][9]. Теперь я хочу удалить каждую строку в этой матрице, которая содержит определенное значение, в данном случае 10, поэтому у меня осталось ...

1 2 3 4 5 6 7 8 9
2 6 4 7 8 4 3 2 5
5 3 6 8 2 7 3 7 2

Ответы [ 8 ]

8 голосов
/ 26 ноября 2009

Вот пример класса, который вы можете запустить, который, я считаю, делает то, что вы ищете. Удаление строк из 2D-массивов - сложная задача, потому что, как сказал @KalebBrasee, вы не можете «удалить» их, а вместо этого вам нужно создать целый новый 2D-массив. Надеюсь, это поможет!

import java.util.ArrayList;
import java.util.List;


public class Matrix
{
    private double[][] data;

    public Matrix(double[][] data)
    {
        int r= data.length;
        int c= data[0].length;
        this.data= new double[r][c];
        for(int i = 0; i < r; i++) {
            for(int j = 0; j < c; j++) {
                    this.data[i][j] = data[i][j];
            }
        }
    }

    /* convenience method for getting a 
       string representation of matrix */
    public String toString()
    {
        StringBuilder sb = new StringBuilder(1024);
        for(double[] row : this.data)
        {
            for(double val : row)
            {
                sb.append(val);
                sb.append(" ");
            }
            sb.append("\n");
        }

        return(sb.toString());
    }

    public void removeRowsWithValue(final double value)
    {
            /* Use an array list to track of the rows we're going to want to 
               keep...arraylist makes it easy to grow dynamically so we don't 
               need to know up front how many rows we're keeping */
        List<double[]> rowsToKeep = new ArrayList<double[]>(this.data.length);
        for(double[] row : this.data)
        {
            /* If you download Apache Commons, it has built-in array search
                      methods so you don't have to write your own */
            boolean found = false;
            for(double testValue : row)
            {
                            /* Using == to compares doubles is generally a bad idea 
                               since they can be represented slightly off their actual
                               value in memory */
                if(Double.compare(value,testValue) == 0)
                {
                    found = true;
                    break;
                }
            }

                    /* if we didn't find our value in the current row, 
                      that must mean its a row we keep */
            if(!found)
            {
                rowsToKeep.add(row);
            }
        }

            /* now that we know what rows we want to keep, make our 
               new 2D array with only those rows */
        this.data = new double[rowsToKeep.size()][];
        for(int i=0; i < rowsToKeep.size(); i++)
        {
            this.data[i] = rowsToKeep.get(i);
        }
    }

    public static void main(String[] args)
    {
        double[][] test = { {1, 2, 3, 4, 5, 6, 7, 8, 9},
                            {6, 2, 7, 2, 9, 6, 8, 10, 5},
                            {2, 6, 4, 7, 8, 4, 3, 2, 5},
                            {9, 8, 7, 5, 9, 7, 4, 1, 10},
                            {5, 3, 6, 8, 2, 7, 3, 7, 2} };

            //make the original array and print it out          
        Matrix m = new Matrix(test);
        System.out.println(m);

            //remove rows with the value "10" and then reprint the array
        m.removeRowsWithValue(10);
        System.out.println(m);
    }
}
5 голосов
/ 26 ноября 2009

Используйте System.arraycopy или используйте java.util.List вместо массивов. ArrayList имеет быстрый доступ к случайным элементам и медленный метод remove, с LinkedList все наоборот. Вы должны выбрать для себя.

1 голос
/ 26 ноября 2009

При и вам нужно воссоздать массив и выбросить старый. Изменение размера существующего массива невозможно - если вы хотите использовать этот тип структуры данных, вам следует построить матрицу на основе коллекций (ArrayList<ArrayList<Double>>), там вы можете легко удалить строку.

Возвращаясь к массивам - идея состоит в том, чтобы собрать все строки (двойные [] массивы), которые вы хотите сохранить, создать массив результатов с этими строками и заменить старый на новый в матрице:

public void doSomethingWith(Matrix in) {
  List<double[]> survivingRows = new ArrayList<double[]>();
  for (double[] row:in.getRows()) {
    if (isAGoodOne(row)) {
      survivingRows.add(row);
    }
  }

  double[][] result = new double[survivingRows][];
  for (int i = 0; i < result.length; i++) {
    result[i] = survivingRows.get(i);
  }
  in.setArray(result);
}
1 голос
/ 26 ноября 2009

Вы не можете удалить элементы из структуры данных встроенного массива Java. Вам нужно будет создать новый массив, длина которого на один меньше, чем у первого массива, и скопировать все массивы в этот массив, КРОМЕ ТОГО, который вы хотите удалить.

0 голосов
/ 13 декабря 2017

Возможно, это не точное решение, а концепция того, как этого добиться с помощью System.arraycopy.

В приведенном ниже примере я хочу скопировать все строки, кроме первой. В вашем случае вы можете пропустить те строки, которые содержат 10.

String[][] src = getSheetData(service, spreadSheetId, range);
String[][] dest = new String[src.length-1][src[0].length];

for (int i = 1; i < src.length; i++) {
System.arraycopy(src[i], 0, dest[i-1], 0, src[0].length-1);
}

Ссылка: https://docs.oracle.com/javase/6/docs/api/java/lang/System.html#arraycopy%28java.lang.Object,%20int,%20java.lang.Object,%20int,%20int%29

0 голосов
/ 22 февраля 2014

Поскольку невозможно избежать создания нового 2D-массива, содержащего после удаленные данные, сначала создайте новый 2D-массив int [] [] b с тем же размером, что и [] []. во-вторых, переберите a [] [], присвойте a b и переместите строку b вверх, если они содержат определенное значение. и здравомыслие проверьте последнюю строку, которая может содержать конкретные данные.

public static int[][] remove(int[][] a, int v) {
    int r = a.length;
    int c = a[0].length;

    int[][] b = new int[r][c];

    int red = 0;
    boolean s = false;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            b[i - red][j] = a[i][j];
            if (a[i][j] == v) {
                red += 1;
                if(i==r-1){
                    s = true;
                }
                break;
            }
        }
    }
    //check last row
    if(s){
    for(int i = r-red;i <r-red +1; i++ )
        for (int j = 0; j<c; j++){
            b[i][j] = 0;
        }
    }
    return b;
}

public static void main(String[] args){
    int[][] a = { {1, 2, 3, 4, 5, 6, 7, 8, 1},
            {6, 2, 7, 2, 9, 6, 8, 10, 5},
            {2, 6, 4, 7, 8, 4, 2, 2, 5},
            {9, 8, 7, 5, 9, 7, 4, 1, 1},
            {5, 3, 6, 8, 2, 7, 3, 1, 1} };

    print(remove(a, 10));


}

public static void print(int[][] a) {
    int r = a.length;
    int c = a[0].length;


    int red = 0;
    for (int i = 0; i < r; i++) {
        System.out.printf("\nrow %d, \n", i);
        for (int j = 0; j < c; j++) {
            System.out.printf("%d, ", a[i][j]);
        }
    }
}
0 голосов
/ 27 ноября 2009

Мой синтаксис Java немного ржавый, но следующее, если рассматривать его как псевдокод, будет работать

public Matrix removeRows(Matrix input) {
    int[][] output = new int[input.numRows][input.numColumns]();
    int i = 0;
    for (int[] row : input.rows()) {      // Matrix.rows() is a method that returns an array of all the rows in the matrix
        if (!row.contains(10)) {
            output[i] = row;
        }
    }
    return output
0 голосов
/ 26 ноября 2009

Мой дубль:

import java.util.Arrays;

public class RemoveArrayRow {
    private static <T> T[] concat(T[] a, T[] b) {
        final int alen = a.length;
        final int blen = b.length;

        if (alen == 0) {
            return b;
        }

        if (blen == 0) {
            return a;
        }

        final T[] result = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), alen + blen);

        System.arraycopy(a, 0, result, 0, alen);
        System.arraycopy(b, 0, result, alen, blen);

        return result;
    }

    public static void main(String[] args) {
        double[][] d  = { {11, 2, 3, 4, 5, 6, 7, 8, 9, 0},
                          {12, 2, 3, 4, 5, 6, 7, 8, 9, 1},
                          {13, 2, 3, 4, 5, 6, 7, 8, 9, 2},
                          {14, 2, 3, 4, 5, 6, 7, 8, 9, 3},
                          {15, 2, 3, 4, 5, 6, 7, 8, 9, 4} };

        //remove the fourth row:

        // (1)
        double[][] d1 = concat(Arrays.copyOf(d, 3), Arrays.copyOfRange(d, 4, 5));

        // (2)
        double[][] d2 = new double[d.length - 1][d[0].length];
        System.arraycopy(d, 0, d2, 0, 3);
        System.arraycopy(d, 4, d2, 3, 1);

        System.out.print(d1.length);
        System.out.print(d2.length);
    }
}

(1)
Если исключить функцию concat(), используемую для объединения двух массивов, это делается в одной строке:
double[][] d1 = concat(Arrays.copyOf(d, 3), Arrays.copyOfRange(d, 4, 5));
См. Также этот вопрос .Отсюда и код для функции concat().

(2)
Этот метод работает быстрее и использует только доступные функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...