我一直在研究这个问题几天,我似乎无法得到我想要的确切结果。我已将我的问题简化为基于数字,以便我能够尽可能清楚地知道我在做什么以及我想要什么。
我从一个较大的List<List<double>>
开始,其中较大的List
中的每个子List
包含3个数字。例如,List
看起来像这样:
[0] 1,2,3
[1] 1,2,3
[2] 1,2,3
[3] 4,5,6
[4] 4,5,6
[5] 4,5,6
[6] 7,8,9
[7] 7,8,9
[8] 7,8,9
其中列表中的每个项目都是不同的序列。我想要完成的是将List
分成一组较小的列表,其中列表中的每个项目都是相似的。所以对于给定的例子:
list1的:
[0] 1,2,3
[1] 1,2,3
[2] 1,2,3
清单2:
[0] 4,5,6
[1] 4,5,6
[2] 4,5,6
列表3:
[0] 7,8,9
[1] 7,8,9
[2] 7,8,9
因此,为了解决我的问题,我创建了一个函数来递归搜索List
并提取相似的序列并将它们添加到单独的列表中。我的功能不仅不起作用,而且我的代码非常冗长和复杂,我觉得应该有类似的解决方案而不是我想做的。任何建议或建议让我朝着正确的方向前进,我们将不胜感激。
答案 0 :(得分:1)
我认为这会为你做到。它适用于您的故障&#39;要求 - 即{1,2,3}等于{3,2,1}等于{2,3,1}。
static void Main(string[] args)
{
List<List<double>> list = new List<List<double>>()
{
new List<double>() { 1,2,3 },
new List<double>() { 4,5,6 },
new List<double>() { 7,8,9 },
new List<double>() { 2,3,1 },
new List<double>() { 5,6,4 },
new List<double>() { 8,9,7 },
new List<double>() { 3,1,2 },
new List<double>() { 6,4,5 },
new List<double>() { 9,7,8 },
};
// Pick a method, they both work
//var q2 = DictionaryMethod(list);
var q2 = LinqAggregateMethod(list);
foreach (var item in q2)
{
Console.WriteLine("List:");
foreach (var item2 in item)
Console.WriteLine($"\t{item2[0]}, {item2[1]}, {item2[2]}");
}
}
static bool ListsAreEqual(List<double> x, List<double> y)
{
foreach (var d in x.Distinct())
{
if (x.Count(i => i == d) != y.Count(i => i == d))
return false;
}
return true;
}
static IEnumerable<IEnumerable<List<double>>> LinqAggregateMethod(List<List<double>> list)
{
var q = list.Aggregate(new List<List<double>>() /* accumulator(ret) initial value */, (ret, dlist) =>
{
// ret = accumulator
// dlist = one of the List<double> from list
// If accumulator doesn't already contain dlist (or it's equal), add it
if (!ret.Any(dlistRet => ListsAreEqual(dlist, dlistRet)))
ret.Add(dlist);
return ret;
});
// At this point, q contains one 'version' of each list.
// foreach item in q, select all the items in list where the lists are equal
var q2 = q.Select(dlist => list.Where(item => ListsAreEqual(dlist, item)));
return q2;
}
static IEnumerable<IEnumerable<List<double>>> DictionaryMethod(List<List<double>> list)
{
var list2 = new Dictionary<List<double>, List<List<double>>>();
// Loop over each List<double> in list
foreach (var item in list)
{
// Does the dictionary have a key that is equal to this item?
var key = list2.Keys.FirstOrDefault(k => ListsAreEqual(k, item));
if (key == null)
{
// No key found, add it
list2[item] = new List<List<double>>();
}
else
{
// Key was found, add item to its value
list2[key].Add(item);
}
}
var q2 = new List<List<List<double>>>();
foreach (var key in list2.Keys)
{
var a = new List<List<double>>();
a.Add(key); // Add the key
a.AddRange(list2[key]); // Add the other lists
q2.Add(a);
}
return q2;
}
答案 1 :(得分:1)
以下是解决此问题的另一种方法。我将它分为两步。
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
(ViewModel as UserCoinViewModel).LoadDataCommand.Execute(null);
// You can also bind a button to this command to trigger it manually.
}
1)从您的收藏中获取所有唯一列表。您可以使用// Sample input:
List<List<double>> lists = new List<List<double>>();
lists.Add(new List<double> { 1, 1, 3 });
lists.Add(new List<double> { 1, 3, 1 });
lists.Add(new List<double> { 3, 1, 1 });
lists.Add(new List<double> { 4, 5, 6 });
lists.Add(new List<double> { 4, 5, 6 });
lists.Add(new List<double> { 6, 5, 4 });
lists.Add(new List<double> { 7, 8, 9 });
lists.Add(new List<double> { 8, 7, 9 });
lists.Add(new List<double> { 9, 8, 7 });
暂时订购它们。这样可以使用SequenceEqual进行比较:
OrderBy
2)现在,每个组都有一组代表。浏览每个代表并获取与您的代表中的元素相匹配的所有列表。在这里,您可以暂时订购它们,以便与List<List<double>> uniqueOrdered = new List<List<double>>();
foreach (var element in lists.Select(x => x.OrderBy(y => y).ToList()))
{
if (!uniqueOrdered.Any(x=> x.SequenceEqual(element)))
{
uniqueOrdered.Add(element);
}
}
:
SequenceEqual
结果组中的列表将保持其原始顺序!
答案 2 :(得分:0)
我尽力缩短所需的代码来完成我想要完成的任务。顺便说一句,我将结果列表放在您将看到的列表中:
以下示例仅用于声明您的列表并放置随机值:
List<List<int>> ContainerList = new List<List<int>>()
{
new List<int>()
{
0, 1, 2
},
new List<int>()
{
3, 4, 6
},
new List<int>()
{
0, 1, 2
},
new List<int>()
{
7, 8, 9
},
};
现在开始有效载荷:
List<List<List<int>>> result = new List<List<List<int>>>();
foreach (var cont in ContainerList)
result.Add(ContainerList.FindAll(x => x.SequenceEqual(cont)));
// the following erase duplicates
result = result.Distinct().ToList();
所以现在你可以将你的子列表作为:
[0] [0] 012
[0] [1] 012
[1] [0] 346 ....
说明:
ContainerList.FindAll(x => x.SequenceEqual(cont))
以下代码段使用谓词:此处的x是列表中的值。
由于它是一个列表列表,你的x将成为一个列表
SequenceEqual意味着Findall函数将按VALUE而不是REFERENCE搜索等式。
接下来我们擦除重复项,因为ContainerList的第一个元素上的Findall将返回一个列表,其中包含对应于给定参数(即x)的所有重复项。
但是随着参数(x)在列表中递增。您将执行尽可能多的FindAll,因为存在相同子集的值。所以在上面的例子中,你将有2个列表2 012;
我希望这是可以理解的。我的英语太可怕了。
答案 3 :(得分:0)
这是我将用于您给出的示例的代码。
static void Main(string[] args)
{
List<List<double>> lists = new List<List<double>>();
lists.Add(new List<double> { 1, 2, 3 });
lists.Add(new List<double> { 1, 2, 3 });
lists.Add(new List<double> { 1, 2, 3 });
lists.Add(new List<double> { 4, 5, 6 });
lists.Add(new List<double> { 4, 5, 6 });
lists.Add(new List<double> { 4, 5, 6 });
lists.Add(new List<double> { 7, 8, 9 });
lists.Add(new List<double> { 7, 8, 9 });
lists.Add(new List<double> { 7, 8, 9 });
lists.Add(new List<double> { 7, 8, 9 });
List<List<List<double>>> sortedLists = new List<List<List<double>>>();
for (int i = 0; i < lists.Count; i++)
{
bool found = false;
if (!(sortedLists.Count == 0))
{
for (int j = 0; j < sortedLists.Count; j++)
{
if (lists[i][0] == sortedLists[j][0][0] && lists[i][1] == sortedLists[j][0][1] && lists[i][2] == sortedLists[j][0][2])
{
found = true;
sortedLists[j].Add(lists[i]);
break;
}
}
}
if (!found)
{
sortedLists.Add(new List<List<double>> { lists[i] });
}
}
}
唯一的问题是内部if语句是专门为此示例设计的。
if (lists[i][0] == sortedLists[j][0][0] && lists[i][1] == sortedLists[j][0][1] && lists[i][2] == sortedLists[j][0][2])
如果您使用3个双重列表中的任何内容,则必须更改。