38 votes

Comment trier un tableau bidimensionnel (rectangulaire) en C# ?

J'ai un tableau bidimensionnel (de chaînes de caractères) qui constitue mon tableau de données (de lignes et de colonnes). Je veux trier ce tableau par n'importe quelle colonne. J'ai essayé de trouver un algorithme pour le faire en C#, mais je n'y suis pas parvenu.

Toute aide est appréciée.

45voto

Marc Gravell Points 482669

Puis-je vérifier - voulez-vous dire un tableau rectangulaire ( [,] )ou un tableau en dents de scie ( [][] ) ?

Il est assez facile de trier un tableau en dents de scie ; j'ai une discussion à ce sujet. aquí . Évidemment, dans ce cas, le Comparison<T> impliquerait une colonne au lieu d'un tri par ordre ordinal - mais très similaire.

Le tri d'un tableau rectangulaire est plus délicat... Je serais sans doute tenté de copier les données dans un tableau rectangulaire ou dans un tableau List<T[]> et trier puis copier en arrière.

Voici un exemple utilisant un tableau en dents de scie :

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])); 
} 

Pour travailler avec un tableau rectangulaire... eh bien, voici du code pour passer de l'un à l'autre à la volée...

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];
        }
    }
}

0 votes

Quelles modifications doivent être apportées à la méthode Sort pour trier les données en mode descendant ?

2 votes

@Homam comparer.Compare(y[col],x[col])) (inversé x y y là)

24voto

MusiGenesis Points 49273

Chargez votre tableau de chaînes de caractères bidimensionnel dans une véritable table de données (System.Data.DataTable), puis utilisez la méthode Select() de l'objet DataTable pour générer un tableau trié d'objets DataRow (ou utilisez un DataView pour un effet similaire).

// 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");

Vous pourriez également écrire votre propre méthode pour trier un tableau à deux dimensions. Les deux approches seraient des expériences d'apprentissage utiles, mais l'approche DataTable vous permettrait de commencer à apprendre une meilleure façon de gérer les tableaux de données dans une application C#.

0 votes

Cela semble intéressant, pouvez-vous poster ou lier des exemples de code s'il vous plaît.

0 votes

C'est fait. Il y a peut-être un bug quelque part - je l'ai écrit dans le bloc-notes.

0 votes

Étonnant que vous ayez écrit cela dans le bloc-notes - en tout cas, cela a très bien fonctionné. Merci.

6voto

Doug L. Points 2216

Ici est un article archivé de Jim Mischel à InformIt qui gère le tri des tableaux multidimensionnels rectangulaires et en dents de scie.

0 votes

Cet exemple ne trie pas réellement le tableau ; le LINQ produira une séquence triée, mais seulement si vous capturez le résultat... il ne trie pas le tableau existant. Cela pourrait être simplement : string[] names = {"Smith", "Snyder", "Baker", "Jonson", "Ballmer"} ; Array.Sort(names) ;

0 votes

Je vois ce que vous voulez dire - je vais supprimer l'exemple erroné, mais laisser le lien vers l'article sur le tri. PS - merci de m'avoir indiqué la raison du vote négatif. On ne voit pas ça souvent, mais c'est vraiment constructif !

0 votes

Le lien est rompu. Il redirige vers la page d'accueil du site.

1voto

David Hall Points 17450

Ce code devrait faire ce que vous cherchez, je ne l'ai pas généralisé pour n par n, mais c'est simple. Ceci dit, je suis d'accord avec MusiGenesis, il faut utiliser un autre objet qui est un peu mieux adapté à cela (surtout si vous avez l'intention de faire une sorte de liaison).

(J'ai trouvé le code aquí )

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]));
}

1voto

Gregory Massov Points 11
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[,] arr = { { 20, 9, 11 }, { 30, 5, 6 } };
            Console.WriteLine("before");
            for (int i = 0; i < arr.GetLength(0); i++)
            {
                for (int j = 0; j < arr.GetLength(1); j++)
                {
                    Console.Write("{0,3}", arr[i, j]);
                }
                Console.WriteLine();
            }
            Console.WriteLine("After");

            for (int i = 0; i < arr.GetLength(0); i++) // Array Sorting
            {
                for (int j = arr.GetLength(1) - 1; j > 0; j--)
                {

                    for (int k = 0; k < j; k++)
                    {
                        if (arr[i, k] > arr[i, k + 1])
                        {
                            int temp = arr[i, k];
                            arr[i, k] = arr[i, k + 1];
                            arr[i, k + 1] = temp;
                        }
                    }
                }
                Console.WriteLine();
            }

            for (int i = 0; i < arr.GetLength(0); i++)
            {
                for (int j = 0; j < arr.GetLength(1); j++)
                {
                    Console.Write("{0,3}", arr[i, j]);
                }
                Console.WriteLine();
            }
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X