对多个数组进行排序和切片[关闭]

Posted

技术标签:

【中文标题】对多个数组进行排序和切片[关闭]【英文标题】:Sort and slice multiple arrays [closed] 【发布时间】:2021-02-06 21:10:34 【问题描述】:

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

var a = new[] 4, 5, 6, 7, 8;
var b = new[] 7, 4, 3, 1, 2;
... (up to 8 arrays)

int length = SortAsc(a, b, ...)

// a -> 4, 7, 5, 6, 8
// b -> 4, 7, 3, 1, 2
// length = 2

【问题讨论】:

除了@RufusL 建议的内容之外,还请澄清您不知道如何实施的部分 - 例如,有很多问题显示如何找到“元素存在于所有数组中”或“移动数组中的元素”......而且“切片”通常假设大块 - 听起来像 1, 2,3,5 + 6, 2,4,5 应该产生 2,5,1,3 + 2,5, 6,4 这听起来不像“切片”,而是移动到我这里 @RufusL 我希望这很清楚。 @AlexeiLevenkov 我正在寻找最好的算法,而不是为了实现 @ptp 完全不清楚 - "4,7" 与t[7, 4, 3, 1, 2] 的“顺序相同”如何? 您说“相同的顺序”,但没有定义该顺序是什么。您只是按价值升序对它们进行排序吗?还是按照它们在一个特定数组中出现的顺序? 【参考方案1】:

您可以使用Intersect 方法(在System.Linq 中)获取所有常用项。然后您可以使用Union 加入与原始数组的交集。因为我们指定intersection.Union(array) 而不是array.Union(intersection),所以intersection 项将首先出现在结果中。另外,set 操作方法(UnionIntersectExcept)会自动删除所有重复项:

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

请注意,这不是性能最好的解决方案,只是一个简单的解决方案。 :)

哦,您可以使用intersection.Count() 获取常见项目的数量。

【讨论】:

不错。 “最佳 ... 内存”请求完全失败,因为它是 O(总数组大小)与 O(1)的内存优化解决方案......但我强烈怀疑 OP 添加内存优化要求只是为了......让人们感到困惑试图回答。 @AlexeiLevenkov 哦,废话。我真的需要学习阅读。 只是为了澄清我的评论 - 当单一算法可以同时优化时间和内存时,这是非常罕见的。在这种特殊情况下,由于 O(total_number_items ^ 2) 时间复杂度,明显的 O(1) 内存使用解决方案(逐个检查所有数组中的每个项目)听起来并不实用。也有可能加快一些仍在原地的检查,但代码会涉及更多(因为没有原地/没有内存使用 LINQ 帮助器)。【参考方案2】:

据我了解,我在控制台应用程序中做了一个示例:

这是程序.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();
                
            

        

这是方法:

public static ArrayKeeper SortAsc(int[] a, int[] b, int[] c, int[] d)
        
            //order arrays
            a = a.OrderBy(o => o).ToArray();
            b = b.OrderBy(o => o).ToArray();
            c = c.OrderBy(o => o).ToArray();
            d = d.OrderBy(o => o).ToArray();

            a = a.OrderByDescending(o => b.Contains(o)).ToArray();
            b = b.OrderByDescending(o => a.Contains(o)).ToArray();
            c = c.OrderByDescending(o => (a.Contains(o) && b.Contains(o))).ToArray();
            d = d.OrderByDescending(o => (a.Contains(o) && b.Contains(o)) && c.Contains(o)).ToArray();

            var resp = new ArrayKeeper();
            resp.Arrays.Add(b);
            resp.Arrays.Add(a);
            resp.Arrays.Add(c);
            resp.Arrays.Add(d);
            return resp;
        

这是一个帮助传输数据的 DTO;

public class ArrayKeeper 
        public ArrayKeeper()
        
            Arrays = new List<int[]>();
        
        public List<int[]> Arrays  get; set; 
    

这是结果:

$ dotnet run
Length: 4
47123
47568
47129
41256

当然,它是一个 POC,它只是使用 LINQ、列表和数组来做你想做的事情的一种方式;

另外我认为它需要某种验证才能更加动态;

【讨论】:

这似乎移动了在所有数组中不常见的项目,如果 7 存在,则将其放在第二位,然后对剩余的项目进行排序。

以上是关于对多个数组进行排序和切片[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

按降序对对象数组进行排序[关闭]

go--sort对数组进行排序

对 50 000 个对象的数组进行排序 - Javascript [关闭]

如何在 Swift 5 中对数组的数组进行排序 [关闭]

在c#中对数组进行排序[关闭]

按多个数组对 Tableview 行进行排序