C# 根据其值对3个列表进行排序

C# 根据其值对3个列表进行排序,c#,.net,algorithm,C#,.net,Algorithm,我有3个列表,包含任意数量的双倍。现在我想将这些列表相互比较并排序。所有列表的长度都相同 排序的关系是: 比较每个元素。元素越多的列表,其顺序越高。我为两个列表编写了一个实现: public static bool isGreater(List<double> first, List<double> second) { int firstCounter = 0; int secondCounter = 0;

我有3个列表,包含任意数量的双倍。现在我想将这些列表相互比较并排序。所有列表的长度都相同

排序的关系是:

比较每个元素。元素越多的列表,其顺序越高。我为两个列表编写了一个实现:

public static bool isGreater(List<double> first, List<double> second)
        {
            int firstCounter = 0;
            int secondCounter = 0;

            for (int i = 0; i < first.Count; i++)
            {
                if (first.ElementAt(i) > second.ElementAt(i))
                {
                    firstCounter++;
                }
                else if (first.ElementAt(i) < second.ElementAt(i))
                {
                    secondCounter++;
                }
            }

            if (firstCounter > secondCounter)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
publicstaticbool更大(先列表,后列表)
{
int firstCounter=0;
int secondCounter=0;
for(int i=0;i第二个元素(i))
{
firstCounter++;
}
else if(第一个元素(i)<第二个元素(i))
{
secondCounter++;
}
}
如果(第一计数器>第二计数器)
{
返回true;
}
其他的
{
返回false;
}
}

但是,如何将此代码改编为3个列表,甚至n个列表?

列表的多样性是一种幻觉-只有一个列表,但每个项目都有一个属性来标识它来自哪个列表

合并列表,排序,然后拆分回其原始列表。

需要执行的操作排序()根据您的排序定义创建列表集合。您应该能够使用标准排序,并为其提供自定义排序功能

算法类似于:

  • 创建要排序的列表数组
  • 对数组调用标准sort()方法,使用上面定义的例程作为comparator函数
  • 编辑:
    这个算法应该给出最大值O(mn lgN)(N列出每个大小M)。我知道有一种更快的(对数因子)随机算法可以找到最大值。你可以阅读。除非要处理大量列表,否则我不建议实现此算法。

    首先,使用已排序的集合不是更容易吗

    你可以用它来做


    关于如何将其应用于n-列表的问题,请使用递归,只需使用集合并跟踪最后的结果。这将允许您比较第一个和第三个列表,例如,如果递归函数的第一次迭代的结果返回第一个列表。

    使用数组为每个列表保留计数器

    如果你有n个列表。你的阵列是计数器

     void SortLists(List<List<double>> lists)
     {
     int[] counter = new int[lists.Count];
    
     for (int i = 0; i < lists[0].Count; i++)
     {
         double MaxValue = double.MinValue;
         int winningList = 0;
    
         for (int j = 0; j < lists.Count; j++)
         {
            if(lists[j].ElementAt(i) > MaxValue )
            {
                MaxValue = lists[j].ElementAt(i);
                winningList = j;
            }
         }
    
         counter[winningList]++;
     }
    
     // sort the counter array, in effect your lists are sorted.
     }
    
    void排序列表(列表)
    {
    int[]计数器=新的int[lists.Count];
    对于(int i=0;i<列表[0]。计数;i++)
    {
    double MaxValue=double.MinValue;
    int winningList=0;
    对于(int j=0;jMaxValue)
    {
    MaxValue=列表[j].ElementAt(i);
    winningList=j;
    }
    }
    计数器[赢取列表]+;
    }
    //对计数器数组进行排序,实际上列表已排序。
    }
    
    var list11=新列表{1,2,3};
    var list22=新列表{4,5,3};
    var list33=新列表{4,1,0};
    int a计数器=0,b计数器=0,c计数器;
    list11.Select((o,i)=>new{a=list11[i],b=list22[i]})
    .Aggregate(0,(初始,项)=>项a>项b
    ?计数器++
    :item.a==item.b
    ?B计数器
    :b计数器++);
    如果(A计数器>B计数器)
    {
    //对列表11和列表33执行相同的操作
    }
    其他的
    {
    //对列表22和列表33执行相同的操作
    }
    

    您可以对其进行重构,为两个列表编写一个函数,并为您想要的每一对调用该函数。

    我对您的方法做了一些修改,并添加了另一个:

    private static List<double> GetGreater(List<double> first, List<double> second)
    {
        int firstCounter = 0;
        int secondCounter = 0;
    
        for (int i = 0; i < first.Count; i++)
        {
            if (first.ElementAt(i) > second.ElementAt(i))
            {
                firstCounter++;
            }
            else if (first.ElementAt(i) < second.ElementAt(i))
            {
                secondCounter++;
            }
        }
    
        // return the greater list instead of bool
        return (firstCounter > secondCounter ? first : second);
    }
    
    
    public static List<double> Greater(params List<double>[] p)
    {
        // assumes the first list is the greater, then check the others
        // this method assumes you will always pass at least 2 lists
    
        List<double> greater = p[0];
    
        for (var i = 1; i < p.Length; ++i)
        {
            greater = GetGreater(greater, p[i]);
        }
    
        return greater;
    }
    
    static void Main(string[] args)
    {
        // lists used for this test
        var l1 = new List<double>() { 1, 222, 3 };
        var l2 = new List<double>() { 1, 2, 4 };
        var l3 = new List<double>() { 11, 222, 333 };
    
        var l4 = Greater(l1, l2, l3); // l3
    }
    
    private static List GetGreater(列表第一,列表第二)
    {
    int firstCounter=0;
    int secondCounter=0;
    for(int i=0;i第二个元素(i))
    {
    firstCounter++;
    }
    else if(第一个元素(i)<第二个元素(i))
    {
    secondCounter++;
    }
    }
    //返回更大的列表,而不是bool
    返回(第一计数器>第二计数器?第一:第二);
    }
    公共静态列表更大(参数列表[]p)
    {
    //假设第一个列表较大,然后检查其他列表
    //此方法假定您将始终传递至少2个列表
    列表大于=p[0];
    对于(变量i=1;i
    我觉得您有一个“外部”列表,其中包含“内部”列表,您希望对“外部”列表进行排序。你可以这样做:

    // Set up some input data
    var outerList = new List<List<double>>();
    outerList.Add(new List<double> { 2.0, 3.0, 3.0 });
    outerList.Add(new List<double> { 1.0, 2.0, 3.0 });
    outerList.Add(new List<double> { 2.0, 2.0, 3.0 });
    
    // Sort the outer list
    outerList.Sort((first, second) => isGreater(first, second) ? 1 : -1);
    

    只要每个列表中的元素数量相同且已知,我就举一个小例子:

    const int listSize = 6;
    
    List<int> one = new List<int> { 0, 1, 2, 3, 4, 5 };
    List<int> two = new List<int> { 10, 1, 9, 2, 8, 3 };
    List<int> three = new List<int> { 5, 5, 5, 5, 5, 5 };
    
    Dictionary<List<int>, int> lists = new Dictionary<List<int>, int>()
    {
        {one, 0},
        {two, 0},
        {three, 0}
    };
    
    for (int i = 0; i < listSize; i++)
    {
        var sortedAtIndex = lists.Keys.OrderByDescending(k => k[i]);
        lists[sortedAtIndex.ElementAt(0)]++;
    }
    
    // And to show you that it works...
    foreach (var element in lists.OrderByDescending(k => k.Value)
        .Select(k => k.Key))
    {
        Console.WriteLine("{0}", lists[element]);
    }
    
    const int listSize=6;
    列表一=新列表{0,1,2,3,4,5};
    列表二=新列表{10,1,9,2,8,3};
    列表三=新列表{5,5,5,5,5};
    字典列表=新字典()
    {
    {1,0},
    {2,0},
    {3,0}
    };
    for(int i=0;ik[i]);
    列出[sortedAtIndex.ElementAt(0)]+;
    }
    //为了让你知道它是有效的。。。
    foreach(lists.OrderByDescending中的var元素(k=>k.Value)
    .选择(k=>k.Key))
    {
    WriteLine(“{0}”,列出[element]);
    }
    
    您应该能够使用LINQ和用于
    IEnumerable
    的自定义IComparer来完成此操作

    公共类EnumerableDoubleComparer:IComparer
    {
    公共整数比较(IEnumerable a,IEnumerable b)
    {
    var counts=a.Select((k,i)=>new{Value=
    
    outerList.Sort(CompareLists);
    
    const int listSize = 6;
    
    List<int> one = new List<int> { 0, 1, 2, 3, 4, 5 };
    List<int> two = new List<int> { 10, 1, 9, 2, 8, 3 };
    List<int> three = new List<int> { 5, 5, 5, 5, 5, 5 };
    
    Dictionary<List<int>, int> lists = new Dictionary<List<int>, int>()
    {
        {one, 0},
        {two, 0},
        {three, 0}
    };
    
    for (int i = 0; i < listSize; i++)
    {
        var sortedAtIndex = lists.Keys.OrderByDescending(k => k[i]);
        lists[sortedAtIndex.ElementAt(0)]++;
    }
    
    // And to show you that it works...
    foreach (var element in lists.OrderByDescending(k => k.Value)
        .Select(k => k.Key))
    {
        Console.WriteLine("{0}", lists[element]);
    }
    
    public class EnumerableDoubleComparer : IComparer<IEnumerable<double>>
    {
        public int Compare( IEnumerable<double> a, IEnumerable<double> b )
        {
            var counts = a.Select( (k,i) => new { Value = k, Index = i } )
                          .Join( b.Select( (k,i) => new { Value = k, Index = i } ),
                                 outer => outer.Index,
                                 inner => inner.Index,
                                 (outer,inner) => outer.Value > inner.Value
                                                      ? "A"
                                                      : (inner.Value > outer.Value
                                                            ? "B"
                                                            : "" ) )
                          .GroupBy( listID => listID )
                          .Select( g => new { g.Key, Count = g.Count() } );
    
            // you could also use SingleOrDefault on the collection and check for null
            var aCount = counts.Where( c => c.Key == "A" )
                               .Select( c => c.Count )
                               .SingleOrDefault();
            var bCount = counts.Where( c => c.Key == "B" )
                               .Select( c => c.Count )
                               .SingleOrDefault();
    
            return aCount - bCount;
        }
    }
    
    var a = new double[] { 1, 1 };
    var b = new double[] { 2, 2 };
    var c = new double[] { 3, 3 };
    
    var lists = new List<IEnumerable<double>> { a, c, b };
    
    var ordered = lists.OrderByDescending( l => l, new EnumerableDoubleComparer() );