una por ordenar metodo matriz matrices columnas burbuja bidimensional ascendente arreglo array alfabeticamente c# arrays sorting

por - ¿Cómo puedo ordenar una matriz bidimensional en C#?



ordenar una matriz en c burbuja (12)

Tengo una matriz bidimensional (de cadenas) que compone mi tabla de datos (de filas y columnas). Quiero ordenar esta matriz por cualquier columna. Traté de encontrar un algoritmo para hacer esto en C #, pero no he tenido éxito.

Cualquier ayuda es apreciada.


¿Puedo verificar, me refiero a una matriz rectangular ( [,] ) o una matriz dentada ( [][] )?

Es bastante fácil ordenar una matriz dentada; Tengo una discusión sobre eso here . Obviamente, en este caso, la Comparison<T> implicaría una columna en lugar de ordenar por ordinal, pero muy similar.

Ordenar una matriz rectangular es más complicado ... Probablemente estaría tentado de copiar los datos en una matriz rectangular o en una List<T[]> , ordenarlos y luego copiarlos.

Aquí hay un ejemplo con una matriz dentada:

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

Para trabajar con una matriz rectangular ... bueno, aquí hay un código para intercambiar entre los dos sobre la marcha ...

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


Así que tu arreglo está estructurado así (voy a hablar en pseudocódigo porque mi C # -fu es débil, pero espero que entiendas lo esencial de lo que estoy diciendo)

string values[rows][columns]

Entonces value[1][3] es el valor en la fila 1, columna 3.

Desea ordenar por columna, por lo que el problema es que su matriz está desactivada 90 grados.

Como primer corte, ¿podrías rotarlo?

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]

Si sabe que solo desea ordenar una columna a la vez, puede optimizar mucho extrayendo los datos que desea ordenar:

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]

En C ++ puedes jugar trucos con la forma de calcular las compensaciones en la matriz (ya que puedes tratar la matriz bidimensional como una matriz unificada) pero no estoy seguro de cómo hacerlo en c #.


Cargue su matriz de cadenas bidimensional en una DataTable real (System.Data.DataTable), y luego use el método Select () del objeto DataTable para generar una matriz ordenada de objetos DataRow (o use una DataView para obtener un efecto similar).

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

También puede escribir su propio método para ordenar una matriz bidimensional. Ambos enfoques serían experiencias de aprendizaje útiles, pero el enfoque de DataTable te ayudaría a aprender una forma mejor de manejar tablas de datos en una aplicación de C #.


Esta es una vieja pregunta, pero esta es una clase que acabo de construir basada en el artículo de Jim Mischel en InformIt vinculado por

class Array2DSort : IComparer<int> { // maintain a reference to the 2-dimensional array being sorted string[,] _sortArray; int[] _tagArray; int _sortIndex; protected string[,] SortArray { get { return _sortArray; } } // constructor initializes the sortArray reference public Array2DSort(string[,] theArray, int sortIndex) { _sortArray = theArray; _tagArray = new int[_sortArray.GetLength(0)]; for (int i = 0; i < _sortArray.GetLength(0); ++i) _tagArray[i] = i; _sortIndex = sortIndex; } public string[,] ToSortedArray() { Array.Sort(_tagArray, this); string[,] result = new string[ _sortArray.GetLength(0), _sortArray.GetLength(1)]; for (int i = 0; i < _sortArray.GetLength(0); i++) { for (int j = 0; j < _sortArray.GetLength(1); j++) { result[i, j] = _sortArray[_tagArray[i], j]; } } return result; } // x and y are integer row numbers into the sortArray public virtual int Compare(int x, int y) { if (_sortIndex < 0) return 0; return CompareStrings(x, y, _sortIndex); } protected int CompareStrings(int x, int y, int col) { return _sortArray[x, col].CompareTo(_sortArray[y, col]); } }

Dada una matriz 2D no ordenada de tamaño arbitrario que desea ordenar en la columna 5, simplemente haga esto:

Array2DSort comparer = new Array2DSort(data, 5); string[,] sortedData = comparer.ToSortedArray();

Tenga en cuenta el método de Compare virtual y SortArray protegido para que pueda crear subclases especializadas que siempre ordenan en una columna en particular o clasifican de forma especializada en varias columnas o lo que quiera hacer. Es por eso que CompareStrings está roto y protegido: cualquier subclase puede usarlo para comparaciones simples en lugar de escribir la SortArray[x, col].CompareTo(SortArray[y, col]) completa SortArray[x, col].CompareTo(SortArray[y, col]) .


Este código debe hacer lo que está buscando, no lo he generalizado para n por n, pero eso es sencillo. Dicho esto: estoy de acuerdo con MusiGenesis, usando otro objeto que se adapta un poco mejor a esto (especialmente si pretendes hacer algún tipo de enlace)

(Encontré el código here )

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


Me gusta el enfoque DataTable propuesto por MusiGenesis arriba. Lo bueno de esto es que puedes ordenar por cualquier cadena SQL ''por orden'' que use nombres de columna, por ejemplo, "x, y desc, z" para ''ordenar por x, y desc, z''. (FWIW, no pude hacer que funcionara usando ordinales de columna, por ejemplo, "3,2,1" para "ordenar por 3,2,1"). Solo usé números enteros, pero claramente se podían agregar datos de tipo mixto en DataTable y ordenarlo de cualquier manera.

En el siguiente ejemplo, primero cargué algunos datos enteros sin clasificar en un tblToBeSorted en Sandbox (no se muestra). Con la tabla y sus datos ya existentes, los cargo (sin clasificar) en una matriz de enteros 2D, luego en una DataTable. La matriz de DataRows es la versión ordenada de DataTable. El ejemplo es un poco extraño porque cargué mi matriz de la base de datos y pude haberlo ordenado en ese momento, pero solo quería obtener una matriz sin clasificar en C # para usar con el objeto 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(); } }


Probar esto. La estrategia básica es ordenar la columna en particular de forma independiente y recordar la fila original de la entrada. El resto del código recorrerá los datos de la columna ordenada y cambiará las filas de la matriz. La parte difícil es recordar actualizar la columna original ya que la parte de intercambio alterará efectivamente la columna original.

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


Sé que es tarde, pero aquí está mi pensamiento que tal vez quieras considerar.

por ejemplo, esto es una matriz

{ m,m,m a,a,a b,b,b j,j,j k,l,m }

y quieres convertirlo por coloumn número 2, luego

string[] newArr = new string[arr.length] for(int a=0;a<arr.length;a++) newArr[a] = arr[a][1] + a; // create new array that contains index number at the end and also the coloumn values Array.Sort(newArr); for(int a=0;a<newArr.length;a++) { int index = Convert.ToInt32(newArr[a][newArr[a].Length -1]); //swap whole row with tow at current index if(index != a) { string[] arr2 = arr[a]; arr[a] = arr[index]; arr[index] = arr2; } }

Felicitaciones, ha ordenado la matriz por coloumn deseado. Puede editar esto para que funcione con otros tipos de datos


Si pudieras obtener los datos como una tupla genérica cuando la lees o la recuperas, sería mucho más fácil; entonces solo tendría que escribir una función de ordenamiento que compare la columna deseada de la tupla, y usted tiene una matriz de tuplas de una sola dimensión.



Here hay un artículo archivado de Jim Mischel en InformIt que maneja la clasificación para matrices multidimensionales rectangulares y dentadas.


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