繁体   English   中英

根据值列出3个列表

[英]Sort 3 list according to their values

我有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;
            }
        }

但是,如何为3个甚至n个列表调整此代码?

你需要做什么sort()根据你的订购定义列表的集合。 您应该能够使用标准排序并为其提供自定义排序功能。

算法类似于:

  1. 创建要排序的列表数组。
  2. 在Arrays上调用标准的sort()方法,使用上面定义的例程作为比较器函数。

编辑:这个算法应该给你最大的O(MN lgN)(N列出每个大小M)。 我知道一个更快速(对数因子)随机算法来找到最大值。 你可以在这里阅读它。 除非您要处理大量的列表,否则我不建议实施此算法。

您应该可以使用LINQ和IEnumerable<double>的自定义IComparer来完成此操作。

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

首先使用已经排序的集合会不会更容易?

你可以使用Sorted Dictonary来做到这一点。

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

使用数组来保存每个列表的计数器。

如果你有n个列表。 你的阵列是Counter

 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.
 }
var list11 = new List<double> { 1, 2, 3 };
var list22 = new List<double> { 4, 5, 3 };
var list33 = new List<double> { 4, 1, 0 };

int acounter = 0, bcounter = 0, ccounter;
list11.Select((o, i) => new { a = list11[i], b = list22[i] })
    .Aggregate(0, (init, item) => item.a > item.b
                                        ? acounter++
                                        : item.a == item.b
                                            ? bcounter
                                            : bcounter++);
if (acounter > bcounter)
{
    //Do the same for list11 and list33
}
else
{
    //Do the same for list22 and list33 
}

you can refactor it and write a function for two list and call that for every pair that you want.

我只想了一点你的方法并添加了另一个:

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
}

听起来像你有一个“内部”列表的“外部”列表,并且你想要对“外部”列表进行排序。 你可以这样做:

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

实际上,你可能最好更改isGreater(它不能返回“两个列表都相等”的结果,这可能会混淆Sort)一个CompareLists函数,如果第一个参数小于第二个,则返回-1,如果是第一个参数大于第二个参数,如果它们相等则为0。 然后你可以打电话:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM