[英]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()根据你的订购定义列表的集合。 您应该能够使用标准排序并为其提供自定义排序功能。
算法类似于:
编辑:这个算法应该给你最大的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.