Как я сортирую двумерный (прямоугольный) массив в C#?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

34
задан Adam 23 February 2019 в 22:22
поделиться

9 ответов

Загрузите свой двумерный массив строк в фактический DataTable (Система. Данные. DataTable), и затем используют Выбор Объекта dataTable () метод, чтобы генерировать сортированный массив объектов DataRow (или использовать DataView для подобного эффекта).

// assumes stringdata[row, col] is your 2D string array
DataTable dt = new DataTable();
// assumes first row contains column names:
for (int col = 0; col < stringdata.GetLength(1); col++)
{
    dt.Columns.Add(stringdata[0, col]);
}
// load data from string array to data table:
for (rowindex = 1; rowindex < stringdata.GetLength(0); rowindex++)
{
    DataRow row = dt.NewRow();
    for (int col = 0; col < stringdata.GetLength(1); col++)
    {
        row[col] = stringdata[rowindex, col];
    }
    dt.Rows.Add(row);
}
// sort by third column:
DataRow[] sortedrows = dt.Select("", "3");
// sort by column name, descending:
sortedrows = dt.Select("", "COLUMN3 DESC");

Вы могли также записать свой собственный метод для сортировки двухмерной антенной решетки. Оба подхода были бы полезным полезным опытом, но подход DataTable запустит Вас при изучении лучшего способа обработать таблицы данных в приложении C#.

25
ответ дан MusiGenesis 27 November 2019 в 16:29
поделиться

Я могу проверить - Вы имеете в виду прямоугольную антенную решетку ([,]) или зубчатый массив ([][])?

довольно легко отсортировать зубчатый массив; у меня есть обсуждение этого здесь . Очевидно, в этом случае эти Comparison<T> включил бы столбец вместо того, чтобы сортировать по ординалу - но очень похожий.

Сортировка прямоугольной антенной решетки более хитра... Я, вероятно, испытал бы желание скопировать данные или в прямоугольную антенную решетку или в List<T[]>, и вид там , затем скопировал бы назад.

Вот пример с помощью зубчатого массива:

static void Main()
{  // could just as easily be string...
    int[][] data = new int[][] { 
        new int[] {1,2,3}, 
        new int[] {2,3,4}, 
        new int[] {2,4,1} 
    }; 
    Sort<int>(data, 2); 
} 
private static void Sort<T>(T[][] data, int col) 
{ 
    Comparer<T> comparer = Comparer<T>.Default;
    Array.Sort<T[]>(data, (x,y) => comparer.Compare(x[col],y[col])); 
} 

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

static T[][] ToJagged<T>(this T[,] array) {
    int height = array.GetLength(0), width = array.GetLength(1);
    T[][] jagged = new T[height][];

    for (int i = 0; i < height; i++)
    {
        T[] row = new T[width];
        for (int j = 0; j < width; j++)
        {
            row[j] = array[i, j];
        }
        jagged[i] = row;
    }
    return jagged;
}
static T[,] ToRectangular<T>(this T[][] array)
{
    int height = array.Length, width = array[0].Length;
    T[,] rect = new T[height, width];
    for (int i = 0; i < height; i++)
    {
        T[] row = array[i];
        for (int j = 0; j < width; j++)
        {
            rect[i, j] = row[j];
        }
    }
    return rect;
}
// fill an existing rectangular array from a jagged array
static void WriteRows<T>(this T[,] array, params T[][] rows)
{
    for (int i = 0; i < rows.Length; i++)
    {
        T[] row = rows[i];
        for (int j = 0; j < row.Length; j++)
        {
            array[i, j] = row[j];
        }
    }
}
41
ответ дан Marc Gravell 27 November 2019 в 16:29
поделиться

Здесь заархивированная статья от Jim Mischel в InformIt, который обрабатывает сортировку и для прямоугольных и для зубчатых многомерных массивов.

6
ответ дан Doug L. 27 November 2019 в 16:29
поделиться

Этот код должен сделать то, что Вы после, я не обобщил его для n n, но это является прямым. Это сказало - я соглашаюсь с MusiGenesis, с помощью другого объекта, который немного лучше подходит для этого (особенно, если Вы намереваетесь сделать какой-либо вид привязки)

(я нашел код здесь )

string[][] array = new string[3][];

array[0] = new string[3] { "apple", "apple", "apple" };
array[1] = new string[3] { "banana", "banana", "dog" };
array[2] = new string[3] { "cat", "hippo", "cat" };         

for (int i = 0; i < 3; i++)
{
   Console.WriteLine(String.Format("{0} {1} {2}", array[i][0], array[i][1], array[i][2]));
}

int j = 2;

Array.Sort(array, delegate(object[] x, object[] y)
  {
    return (x[j] as IComparable).CompareTo(y[ j ]);
  }
);

for (int i = 0; i < 3; i++)
{
  Console.WriteLine(String.Format("{0} {1} {2}", array[i][0], array[i][1], array[i][2]));
}
1
ответ дан Jason Plank 27 November 2019 в 16:29
поделиться

Таким образом, Ваш массив структурирован как это (я собираюсь говорить в псевдокоде, потому что мой C#-fu слаб, но я надеюсь, что Вы получаете суть того, что я говорю)

string values[rows][columns]

, Таким образом value[1][3] значение в строке 1, столбец 3.

, который Вы хотите отсортировать по столбцу, таким образом, проблема состоит в том, что Ваш массив выключен на 90 градусов.

Как первое сокращение, Вы могли просто повернуть его?

std::string values_by_column[columns][rows];

for (int i = 0; i < rows; i++)
  for (int j = 0; j < columns; j++)
    values_by_column[column][row] = values[row][column]

sort_array(values_by_column[column])

for (int i = 0; i < rows; i++)
  for (int j = 0; j < columns; j++)
    values[row][column] = values_by_column[column][row]

, Если Вы знаете, Вы только хотите отсортировать один столбец за один раз, Вы могли бы оптимизировать это много, просто извлекая данные, которые Вы хотите отсортировать:

  string values_to_sort[rows]
  for (int i = 0; i < rows; i++)
    values_to_sort[i] = values[i][column_to_sort]

  sort_array(values_to_sort)

  for (int i = 0; i < rows; i++)
    values[i][column_to_sort] = values_to_sort[i]

В C++ Вы могли выделывать фокусы с тем, как вычислить смещения в массив (так как Вы могли рассматривать свою двухмерную антенную решетку как один-d массив), но я не уверен, как сделать это в c#.

0
ответ дан Moishe Lettvin 27 November 2019 в 16:29
поделиться

Испытайте это. Основная стратегия состоит в том, чтобы отсортировать конкретный столбец независимо и помнить исходную строку записи. Остальная часть кода циклически повторится через отсортированные данные столбца и выгрузит строки в массиве. Хитрая часть является remembing для обновления первоначального столбца, поскольку часть подкачки эффективно изменит первоначальный столбец.


        public class Pair<T> {
            public int Index;
            public T Value;
            public Pair(int i, T v) {
                Index = i;
                Value = v;
            }
        }
        static IEnumerable<Pair<T>> Iterate<T>(this IEnumerable<T> source) {
            int index = 0;
            foreach ( var cur in source) {
                yield return new Pair<T>(index,cur);
                index++;
            }
        }
        static void Sort2d(string[][] source, IComparer comp, int col) {
            var colValues = source.Iterate()
                .Select(x => new Pair<string>(x.Index,source[x.Index][col])).ToList();
            colValues.Sort((l,r) => comp.Compare(l.Value, r.Value));
            var temp = new string[source[0].Length];
            var rest = colValues.Iterate();
            while ( rest.Any() ) {
                var pair = rest.First();
                var cur = pair.Value;
                var i = pair.Index;
                if (i == cur.Index ) {
                    rest = rest.Skip(1);
                    continue;
                }

                Array.Copy(source[i], temp, temp.Length);
                Array.Copy(source[cur.Index], source[i], temp.Length);
                Array.Copy(temp, source[cur.Index], temp.Length);
                rest = rest.Skip(1);
                rest.Where(x => x.Value.Index == i).First().Value.Index = cur.Index;
            }
        }

        public static void Test1() {
            var source = new string[][] 
            {
                new string[]{ "foo", "bar", "4" },
                new string[] { "jack", "dog", "1" },
                new string[]{ "boy", "ball", "2" },
                new string[]{ "yellow", "green", "3" }
            };
            Sort2d(source, StringComparer.Ordinal, 2);
        }
0
ответ дан JaredPar 27 November 2019 в 16:29
поделиться

Если Вы могли бы получить данные как универсальный кортеж, когда Вы считаете их в или получили их, это будет намного легче; тогда необходимо было бы просто записать функцию Вида, которая сравнивает требуемый столбец кортежа, и у Вас есть единственный массив размера кортежей.

0
ответ дан Raindog 27 November 2019 в 16:29
поделиться

Массив. Вид (массив, (a, b) => {возвращаются [0] - b [0];});

0
ответ дан 27 November 2019 в 16:29
поделиться

Мне нравится подход DataTable, предложенный MusiGenesis выше. Приятно то, что вы можете сортировать по любой допустимой строке SQL 'order by', которая использует имена столбцов, например «x, y desc, z» для 'порядок по x, y desc, z'. (FWIW, мне не удалось заставить его работать, используя порядковые номера столбцов, например, «3,2,1» для «порядка 3,2,1»). Я использовал только целые числа, но очевидно, что вы могли добавить данные смешанного типа в DataTable и отсортируйте его любым способом.

В приведенном ниже примере я сначала загрузил некоторые несортированные целочисленные данные в tblToBeSorted в песочнице (не показано). Поскольку таблица и ее данные уже существуют, я загружаю ее (без сортировки) в двумерный целочисленный массив, а затем в DataTable. Массив DataRows - это отсортированная версия DataTable. Пример немного странный, так как я загружаю свой массив из БД и мог бы отсортировать его тогда, но я просто хотел получить несортированный массив в C # для использования с объектом DataTable.

static void Main(string[] args)
{
    SqlConnection cnnX = new SqlConnection("Data Source=r90jroughgarden\\;Initial Catalog=Sandbox;Integrated Security=True");
    SqlCommand cmdX = new SqlCommand("select * from tblToBeSorted", cnnX);
    cmdX.CommandType = CommandType.Text;
    SqlDataReader rdrX = null;
    if (cnnX.State == ConnectionState.Closed) cnnX.Open();

    int[,] aintSortingArray = new int[100, 4];     //i, elementid, planid, timeid

    try
    {
        //Load unsorted table data from DB to array
        rdrX = cmdX.ExecuteReader();
        if (!rdrX.HasRows) return;

        int i = -1;
        while (rdrX.Read() && i < 100)
        {
            i++;
            aintSortingArray[i, 0] = rdrX.GetInt32(0);
            aintSortingArray[i, 1] = rdrX.GetInt32(1);
            aintSortingArray[i, 2] = rdrX.GetInt32(2);
            aintSortingArray[i, 3] = rdrX.GetInt32(3);
        }
        rdrX.Close();

        DataTable dtblX = new DataTable();
        dtblX.Columns.Add("ChangeID");
        dtblX.Columns.Add("ElementID");
        dtblX.Columns.Add("PlanID");
        dtblX.Columns.Add("TimeID");
        for (int j = 0; j < i; j++)
        {
            DataRow drowX = dtblX.NewRow();
            for (int k = 0; k < 4; k++)
            {
                drowX[k] = aintSortingArray[j, k];
            }
            dtblX.Rows.Add(drowX);
        }

        DataRow[] adrowX = dtblX.Select("", "ElementID, PlanID, TimeID");
        adrowX = dtblX.Select("", "ElementID desc, PlanID asc, TimeID desc");

    }
    catch (Exception ex)
    {
        string strErrMsg = ex.Message;
    }
    finally
    {
        if (cnnX.State == ConnectionState.Open) cnnX.Close();
    }
}
0
ответ дан 27 November 2019 в 16:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: