gpt4 book ai didi

c# - 用于索引到 IEnumerableObjects 以实现高效多维数组排序的动态 LINQ 查询字符串

转载 作者:太空宇宙 更新时间:2023-11-03 12:59:26 25 4
gpt4 key购买 nike

我一直在尝试找出最有效和灵活的方法来按多列对多维数组进行排序,其中排序条件直到运行时才知道。

起初,我使用三种不同的方法来处理 DataTables 和排序:DataTable.Select、DataView.Sort,以及在 DataTable 上使用 LINQ。前两种方法允许您通过构建排序字符串在运行时动态指定排序条件。

经过一番研究后,我发现了 Dynamic LINQ,它允许您通过类似于传递给 DataTable.Select 或 DataView.Sort 的字符串执行 OrderBy、ThenBy 等操作:http://dynamiclinq.azurewebsites.net/GettingStarted https://www.nuget.org/packages/System.Linq.Dynamic/

还有关于并行 LINQ,以便您可以在排序中使用多个内核(与数据表不兼容,因为它们不是线程安全的):https://msdn.microsoft.com/en-us/library/dd460688(v=vs.110).aspx

因此,我认为我可以根据运行时提供的多个排序条件,以比使用 DataTable 更有效的方法执行多维数组排序。

我想出了下面的代码。但是,如果我将数据包装在自定义对象中,我只能让 Dynamic LINQ 和 Parallel LINQ 工作,因为我不知道如何为列表或锯齿状数组构建动态 LINQ 查询字符串。

有谁知道我需要对 Dynamic LINQ 的查询字符串做哪些更改才能使我的排序正常工作?我在下面的代码中尝试更正的字符串是“0 ASC、2 DESC、1 ASC”。

请注意,当我将数据包装在名为 Row 的自定义对象中时,我可以很好地构建 DLINQ 字符串并对其进行正确排序。但如果能摆脱这将产生的额外开销,那就太好了。

我下面的代码按 3 列对测试数组进行排序。我使用 LINQ 和 Dynamic LINQ 的各种方法混合使用测试用例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;

namespace MultiDimensionalArraySorting
{
class Program
{
static void Main(string[] args)
{

var testArray = new IComparable[,]{
{1, "a", new DateTime(2000, 1, 1)},
{2, "a", new DateTime(2000, 1, 2)},
{1, "c", new DateTime(2000, 1, 1)},
{5, "a", new DateTime(2000, 1, 1)},
{2, "a", new DateTime(2000, 1, 1)},
};
int numRows = testArray.GetLength(0);
int numCols = testArray.GetLength(1);

var listOfRows = TwoDimensionalArrayToListOfRows(testArray);

var aSortedUsingLinqOnListOfRows = new IComparable[numRows, numCols];
var sortedByLinqOnListOfRows = listOfRows.AsParallel().OrderBy(r => r.Values[0]).ThenByDescending(r => r.Values[2]).ThenBy(r => r.Values[1]);
ListOfRowsToTwoDimensionalArray(sortedByLinqOnListOfRows, ref aSortedUsingLinqOnListOfRows);
Console.WriteLine("\nLinq on list of custom type:");
PrintMultiDimensionalArray(aSortedUsingLinqOnListOfRows);

var aSortedUsingDLinqOnListOfRows = new IComparable[numRows, numCols];
var sortedByDLinqOnListOfRows = listOfRows.AsParallel().OrderBy("Values[0] ASC, Values[2] DESC, Values[1] ASC");
ListOfRowsToTwoDimensionalArray(sortedByDLinqOnListOfRows, ref aSortedUsingDLinqOnListOfRows);
Console.WriteLine("\n\nDLinq on list of custom type:");
PrintMultiDimensionalArray(aSortedUsingDLinqOnListOfRows);

var listOfList = TwoDimensionalArrayToListOfList(testArray);

var aSortedUsingLinqOnListOfList = new IComparable[numRows, numCols];
var sortedByLinqOnListOfList = listOfList.AsParallel().OrderBy(r => r[0]).ThenByDescending(r => r[2]).ThenBy(r => r[1]);
ListOfListToTwoDimensionalArray(sortedByLinqOnListOfList, ref aSortedUsingLinqOnListOfList);
Console.WriteLine("\n\nLinq on list of list:");
PrintMultiDimensionalArray(aSortedUsingLinqOnListOfList);

var aSortedUsingDLinqOnListOfList = new IComparable[numRows, numCols];
var sortedByDLinqOnListOfList = listOfList.AsParallel().OrderBy("0 ASC, 2 DESC, 1 ASC"); //The string provided is incorrect here
ListOfListToTwoDimensionalArray(sortedByDLinqOnListOfList, ref aSortedUsingDLinqOnListOfList);
Console.WriteLine("\n\nDLinq on list of list (incorrect):");
PrintMultiDimensionalArray(aSortedUsingDLinqOnListOfList);

var jaggedArray = TwoDimensionalArrayToJagged(testArray);

var aSortedUsingLinqOnJagged = new IComparable[numRows, numCols];
var sortedJaggedLinq = jaggedArray.AsParallel().OrderBy(r => r[0]).ThenByDescending(r => r[2]).ThenBy(r => r[1]);
JaggedArrayToTwoDimensional(sortedJaggedLinq, ref aSortedUsingLinqOnJagged);
Console.WriteLine("\n\nLinq on jagged array:");
PrintMultiDimensionalArray(aSortedUsingLinqOnJagged);

var aSortedUsingDLinqOnJagged = new IComparable[numRows, numCols];
var sortedUsingDLinqOnJagged = jaggedArray.AsParallel().OrderBy("0 ASC, 2 DESC, 1 ASC"); //The string provided is incorrect here
JaggedArrayToTwoDimensional(sortedUsingDLinqOnJagged, ref aSortedUsingDLinqOnJagged);
Console.WriteLine("\n\nDLinq on jagged array(incorrect):");
PrintMultiDimensionalArray(aSortedUsingDLinqOnJagged);

Console.Read();
}

static void PrintMultiDimensionalArray(IComparable[,] a)
{
int rowStart = a.GetLowerBound(0);
int rowEnd = a.GetUpperBound(0);
int colStart = a.GetLowerBound(1);
int colEnd = a.GetUpperBound(1);
for (int r = rowStart; r <= rowEnd; r++)
{
if (colStart != colEnd)
{
for (int c = colStart; c < colEnd; c++)
Console.Write("{0}, ", a[r, c]);
}
Console.WriteLine(a[r, colEnd]);
}
}

static void JaggedArrayToTwoDimensional(IEnumerable<IComparable[]> jagged, ref IComparable[,] a)
{
int rowStart = a.GetLowerBound(0);
int colStart = a.GetLowerBound(1);
int rowIndex = rowStart;
foreach (var row in jagged)
{
int colIndex = colStart;
foreach (var val in row)
{
a[rowIndex, colIndex++] = val;
}
rowIndex++;
}
}

static void ListOfListToTwoDimensionalArray(IEnumerable<List<IComparable>> rows, ref IComparable[,] a)
{
int r = 0;
foreach (var row in rows)
{
int c = 0;
foreach (var val in row)
a[r, c++] = val;
r++;
}
}

static void ListOfRowsToTwoDimensionalArray(IEnumerable<Row> rows, ref IComparable[,] a)
{
int r = 0;
foreach (var row in rows)
{
int c = 0;
foreach (var val in row.Values)
a[r, c++] = val;
r++;
}
}

static List<Row> TwoDimensionalArrayToListOfRows(IComparable[,] a)
{
int rowStart = a.GetLowerBound(0);
int rowEnd = a.GetUpperBound(0);
var l = new List<Row>(rowEnd - rowStart + 1);
for (int r = rowStart; r <= rowEnd; r++)
l.Add(new Row(a, r));
return l;
}

static List<List<IComparable>> TwoDimensionalArrayToListOfList(IComparable[,] a)
{
int rowStart = a.GetLowerBound(0);
int rowEnd = a.GetUpperBound(0);
int numRows = rowEnd - rowStart + 1;
int colStart = a.GetLowerBound(1);
int colEnd = a.GetUpperBound(1);
int numCols = colEnd - colStart + 1;
var l = new List<List<IComparable>>(numRows);
for (int r = rowStart; r <= rowEnd; r++)
{
var row = new List<IComparable>(numCols);
for (int c = colStart; c <= colEnd; c++)
row.Add(a[r, c]);
l.Add(row);
}
return l;
}

static IComparable[][] TwoDimensionalArrayToJagged(IComparable[,] a)
{
int rowStart = a.GetLowerBound(0);
int rowEnd = a.GetUpperBound(0);
int numRows = rowEnd - rowStart + 1;
int colStart = a.GetLowerBound(1);
int colEnd = a.GetUpperBound(1);
int numCols = colEnd - colStart + 1;

var jagged = new IComparable[numRows][];
for (int r = rowStart; r <= rowEnd; r++)
{
int rowIndex = r - rowStart;
jagged[rowIndex] = new IComparable[numCols];
for (int c = colStart; c <= colEnd; c++)
jagged[rowIndex][c - colStart] = a[r, c];
}

return jagged;
}

public class Row
{
public Row(IComparable[,] a, int rowIndex)
{
int colStart = a.GetLowerBound(1);
int colEnd = a.GetUpperBound(1);
Values = new IComparable[colEnd - colStart + 1];

for (int c = colStart; c <= colEnd; c++)
Values[c - colStart] = a[rowIndex, c];
}
public IComparable[] Values { get; private set; }
}
}
}

最佳答案

我想通了,您应该使用此处定义的关键字“it”: http://dynamiclinq.azurewebsites.net/Expressions

所以在这种情况下排序字符串将是:“it[0] ASC, it[2] DESC, it[1] ASC”

看看锯齿数组方法在大型数据集上的运行速度会很有趣。我怀疑它会比使用 DataTable 快得多

关于c# - 用于索引到 IEnumerableObjects 以实现高效多维数组排序的动态 LINQ 查询字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32773480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com