Как отсортировать двумерный (прямоугольный) массив в C #? - PullRequest
33 голосов
/ 24 октября 2008

У меня есть двумерный массив (из строк), который составляет мою таблицу данных (из строк и столбцов). Я хочу отсортировать этот массив по любому столбцу. Я пытался найти алгоритм для этого в C #, но безуспешно.

Любая помощь приветствуется.

Ответы [ 12 ]

0 голосов
/ 24 октября 2008

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


        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 голосов
/ 24 октября 2008

Итак, ваш массив структурирован следующим образом (я буду говорить в псевдокоде, потому что мой 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 ++ вы могли бы поиграть с тем, как рассчитать смещения в массиве (поскольку вы можете рассматривать ваш двумерный массив как массив с одним целым), но я не уверен, как это сделать в c #.

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