C# 对多个数组进行排序和切片

C# 对多个数组进行排序和切片,c#,arrays,algorithm,sorting,C#,Arrays,Algorithm,Sorting,我有多个对象数组T->其中T:IComparable。 每个数组包含唯一的元素。一个元素可以出现在多个数组中,但不能在同一数组中出现多次。我需要将所有数组中包含的所有元素移动到数组的前面(以相同的顺序),并获取元素的计数(移动后,我可以获得每个数组的一个片段)。在性能/内存方面,什么是最优化的算法 var a=new[]{4,5,6,7,8}; var b=新[]{7,4,3,1,2}; ... (最多8个阵列) int length=SortAsc(a,b,…) //a->{4,7,5,6,8

我有多个对象数组
T->其中T:IComparable
。 每个数组包含唯一的元素。一个元素可以出现在多个数组中,但不能在同一数组中出现多次。我需要将所有数组中包含的所有元素移动到数组的前面(以相同的顺序),并获取元素的计数(移动后,我可以获得每个数组的一个片段)。在性能/内存方面,什么是最优化的算法

var a=new[]{4,5,6,7,8};
var b=新[]{7,4,3,1,2};
... (最多8个阵列)
int length=SortAsc(a,b,…)
//a->{4,7,5,6,8}
//b->{4,7,3,1,2}
//长度=2

您可以使用
Intersect
方法(在
System.Linq
中)获取所有公共项。然后可以使用
并集
将交点与原始数组连接起来。因为我们指定了
intersection.Union(array)
而不是
array.Union(intersection)
,所以
交叉点
项将首先出现在结果中。此外,设置的操作方法(
Union
Intersect
除外)将自动删除任何重复项:

var a = new[] {4, 5, 6, 7, 8};
var b = new[] {7, 4, 3, 1, 2};

// Common items, ordered by value ascending
var intersection = a.Intersect(b).OrderBy(i => i);

// Union the intersection to put the intersected items first 
// (the duplicates are removed automatcially by Union)
a = intersection.Union(a).ToArray();
b = intersection.Union(b).ToArray();
要获得多个数组的交集,可以方便地将它们添加到列表中,然后我们可以使用
Aggregate
方法:

var a = new[] {4, 5, 6, 7, 8};
var b = new[] {7, 4, 3, 1, 2};
var c = new[] {9, 1, 7, 4, 2};
var d = new[] {3, 1, 4, 2, 7};
var e = new[] {3, 7, 4, 1, 2};
var f = new[] {7, 4, 3, 1, 9};
var g = new[] {4, 1, 7, 9, 8};
var h = new[] {3, 2, 6, 7, 4};

var arrays = new List<int[]> {a, b, c, d, e, f, g, h};

var intersection = arrays.Aggregate((accumulation, next) =>
    accumulation.Intersect(next).ToArray()).OrderBy(i => i);
var a=new[]{4,5,6,7,8};
var b=新[]{7,4,3,1,2};
var c=新[]{9,1,7,4,2};
var d=新[]{3,1,4,2,7};
var e=新[]{3,7,4,1,2};
var f=新[]{7,4,3,1,9};
var g=新[]{4,1,7,9,8};
var h=新[]{3,2,6,7,4};
var数组=新列表{a,b,c,d,e,f,g,h};
变量交集=数组。聚合((累积,下一个)=>
construction.Intersect(next.ToArray()).OrderBy(i=>i);
请注意,这不是性能最好的解决方案,只是一个简单的编写方法。:)


哦,你可以使用
intersection.count()

获得常见项目的计数根据我的理解,我在一个控制台应用程序中做了一个示例:

这是program.cs

static void Main(string[] args)
        {
            var a = new int[5] { 4, 5, 6, 7, 8 };
            var b = new int[5] { 7, 4, 3, 1, 2 };
            var c = new int[5] { 4, 2, 1, 7, 9 };
            var d = new int[5] { 1, 2, 6, 4, 5 };
            
            var leng = SortAsc(a, b, c, d);
            if (leng.Arrays.Count > 0)
            {
                Console.WriteLine($"Length: {leng.Arrays.Count}");
                foreach (var item in leng.Arrays)
                {
                    for (int i = 0; i < item.Length; i++)
                    {
                        Console.Write($"{item[i]}");
                    }
                    Console.WriteLine();
                }
            }

        }
这是帮助传输数据的DTO

public class ArrayKeeper {
        public ArrayKeeper()
        {
            Arrays = new List<int[]>();
        }
        public List<int[]> Arrays { get; set; }
    }
当然,这是一个POC,只是一种使用LINQ、列表和数组来完成某些事情的方法


我还认为它需要某种验证才能更具活力

除了@RufusL建议的内容外,还请澄清您不知道如何实现的部分-例如,有许多问题显示如何查找“所有数组中存在的元素”或“移动数组中的元素”。。。此外,“切片”通常假定大块-听起来像{1,2,3,5}+{6,2,4,5}应该产生{2,5,1,3}+{2,5,6,4},听起来不像“切片”,而是移动到me@RufusL我希望这是清楚的。@AlexeiLevenkov我在寻找最好的算法,而不是implementation@ptp绝对不清楚,“4,7”是如何“按相同顺序”的正如
t[7,4,3,1,2]
?您说的是“相同的顺序”,但没有定义该顺序是什么。你只是按价值升序排序吗?或者按照它们在一个特定数组中出现的顺序?很好。在“最佳…内存”请求上完全失败,因为内存最佳解决方案是O(总阵列大小)与O(1)。。。但我强烈怀疑OP增加内存优化需求只是为了。。。迷惑试图回答的人。@AlexeiLevenkov哦,废话。我真的需要学习阅读。我只是想澄清一下我的评论——当单一的算法可以同时获得最多的时间和内存时,这是非常罕见的。在这种特殊情况下,有一个明显的O(1)内存使用解决方案(逐个检查所有数组中的每个项目),由于O(总项目数^2)的时间复杂性,听起来不太实际。还可以加快某些仍在执行的检查,但代码将涉及更多内容(因为没有就地/无内存使用LINQ helpers)。这似乎会移动并非所有数组中常见的项,将
7
放在第二位(如果存在),然后对剩余项进行排序。
public class ArrayKeeper {
        public ArrayKeeper()
        {
            Arrays = new List<int[]>();
        }
        public List<int[]> Arrays { get; set; }
    }
$ dotnet run
Length: 4
47123
47568
47129
41256