我有一对数字列表:
List<Tuple<int, int>> pairs = new List<Tuple<int, int>>();
a. pairs.Add(Tuple.Create<int, int>(1, 2));
b. pairs.Add(Tuple.Create<int, int>(3, 4));
c. pairs.Add(Tuple.Create<int, int>(3, 5));
d. pairs.Add(Tuple.Create<int, int>(5, 6));
e. pairs.Add(Tuple.Create<int, int>(10, 11));
f. pairs.Add(Tuple.Create<int, int>(2, 3));
我希望将它们加入到另一个列表或词典中,如果它们相关则将它们分组。
在上面的示例中,逐步的结果应该是:
一个。 result[0] = {1, 2}
湾result[0] = {1, 2} result[1] = {3, 4}
C。 result[0] = {1, 2} result[1] = {3, 4, 5}
(因为3在那里,所以[1]增加了5)
d。 result[0] = {1, 2} result[1] = {3, 4, 5, 6}
(自那以后有5人被加入[1])
即result[0] = {1, 2} result[1] = {3, 4, 5, 6} result[2] { 10, 11 }
F。 result[0] = {1, 2, 3, 4, 5, 6} result[2] { 10, 11 }
(3被添加到[0],因为2在那里,这使得[1]与[0]合并,因为3在[1]中)
最终结果:result[0] = {1, 2, 3, 4, 5, 6} result[2] { 10, 11 }
有没有简单的方法可以做到这一点? 感谢
答案 0 :(得分:0)
以下是名为PairList
的列表的实现,该列表具有Add
方法,该方法接受元组并执行您想要的操作。
注意:我冒昧地将List<Tuple<int,int>>
更改为List<List<int>>
,因为您的'对'在加入时可能包含多个数字。
使用示例:
PairList pairs = new PairList();
pairs.Add(Tuple.Create(1, 2));
pairs.Add(Tuple.Create(3, 4));
pairs.Add(Tuple.Create(3, 5));
pairs.Add(Tuple.Create(5, 6));
pairs.Add(Tuple.Create(10, 11));
pairs.Add(Tuple.Create(2, 3));
foreach(List<int> list in pairs) {
Console.WriteLine(string.Join(",", list));
}
// Output:
// 1,2,3,4,5,6
// 10,11
实现:
public class PairList : List<List<int>>
{
public void Add(Tuple<int, int> pair)
{
// convert from Tuple<int, int> to List<int>
List<int> newList = new List<int>() { pair.Item1, pair.Item2 };
newList = newList.OrderBy(i => i).ToList(); // sort
// tries to join the new list to any of the existing lists
List<int> joinedList = null;
for(int i = Count-1; i>=0; --i) {
if(TryJoin(newList, this[i], out joinedList)) {
this[i] = joinedList;
break;
}
}
if(joinedList == null) {
// the new list was not joined with any of the existing lists
// so just add it
Add(newList);
return;
}
// the new list was joined with one of the existing lists
// so compare all lists with each other and check if they can be joined
// repeat until no list was joined
do {
joinedList = null;
for(int i = Count-1; i>=0; --i) {
for(int j = Count-1; j>=0; --j) {
if(i == j) continue;
if(TryJoin(this[i], this[j], out joinedList)) {
this[i] = joinedList;
this.RemoveAt(j);
// break out of both for loops
i = -1;
j = -1;
}
}
}
} while(joinedList != null);
}
private bool TryJoin(List<int> list1, List<int> list2, out List<int> joinedList)
{
int low1 = list1[0];
int low2 = list2[0];
int high2 = list2.Last();
// I'm assuming these two conditions are the only valid ones to join
if(low1 == low2 || low1 == high2){
joinedList = new List<int>(list1);
joinedList.AddRange(list2);
joinedList = joinedList.Distinct().OrderBy(j => j).ToList();
return true;
}
joinedList = null;
return false;
}
}
答案 1 :(得分:0)
这会生成您指定的输出 - 但对于大型数据集它不会非常有效!
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
class Program
{
static void Main()
{
var pairs = new List<Tuple<int, int>>
{
Tuple.Create(1, 2),
Tuple.Create(3, 4),
Tuple.Create(3, 5),
Tuple.Create(5, 6),
Tuple.Create(10, 11),
Tuple.Create(2, 3),
};
var groups = new List<List<int>>();
foreach (var pair in pairs)
{
var g1 = groups.Select((g, i) => (g, i)).FirstOrDefault(h => h.g.Contains(pair.Item1));
var g2 = groups.Select((g, i) => (g, i)).FirstOrDefault(h => h.g.Contains(pair.Item2));
if (g1.g == null && g2.g == null)
{
groups.Add(new List<int>{ pair.Item1, pair.Item2 });
}
else if (ReferenceEquals(g1.g, g2.g)) // Pair already in a single group.
{
// Do nothing.
}
else if (g1.g != null && g2.g != null) // Pair appears in two different groups, so join them.
{
g1.g.AddRange(g2.g);
g1.g = g1.g.Distinct().ToList();
groups.RemoveAt(g2.i);
}
else if (g1.g != null) // First of pair appears in g1, so add second of pair.
{
g1.g.Add(pair.Item2);
}
else // Second of pair appears in g2, so add first of pair.
{
g2.g.Add(pair.Item1);
}
}
foreach (var group in groups)
{
Console.WriteLine(string.Join(", ", group));
}
}
}
}
答案 2 :(得分:0)
这是我第一次尝试它。在此处运行:https://dotnetfiddle.net/Mqq5dQ
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<Tuple<int, int>> pairs = new List<Tuple<int, int>>();
pairs.Add(Tuple.Create<int, int>(1, 2));
pairs.Add(Tuple.Create<int, int>(3, 4));
pairs.Add(Tuple.Create<int, int>(3, 5));
pairs.Add(Tuple.Create<int, int>(5, 6));
pairs.Add(Tuple.Create<int, int>(10, 11));
pairs.Add(Tuple.Create<int, int>(2, 3));
var results = new List<List<int>>();
foreach(var pair in pairs)
{
var found = false;
foreach(var result in results)
{
var item1Found = result.Contains(pair.Item1);
var item2Found = result.Contains(pair.Item2);
if(item1Found && item2Found){
found = true;
break;
}
if(item1Found && !item2Found){
AddNum(result, results, pair.Item1, pair.Item2);
found = true;
break;
}
if(item2Found && !item1Found){
AddNum(result, results, pair.Item2, pair.Item1);
found = true;
break;
}
}
if(!found){
results.Add(new List<int> { pair.Item1, pair.Item2 });
}
}
foreach(var result in results)
{
Console.WriteLine(string.Join(", ", result.OrderBy(i => i).ToArray()));
}
}
public static void AddNum(List<int> result, List<List<int>> results, int existing, int newnum)
{
result.Add(newnum);
foreach(var otherresult in results){
if(otherresult != result){
if(otherresult.Contains(newnum)){
var newresult = result.Concat(otherresult).Distinct().ToArray();
result.Clear();
result.AddRange(newresult);
results.Remove(otherresult);
break;
}
}
}
}
}
答案 3 :(得分:0)
谢谢大家,那很快...... 我之前提出过这个解决方案,我认为有一个更简单的解决方案。你发布的一些代码要好得多,所以我打算带它们。谢谢!
DECLARE @InventoryIDList TABLE(JoiningID INT IDENTITY(1,1), ID INT)
DECLARE @ProductSupplierIDList TABLE(JoiningID INT IDENTITY(1,1), ID INT)
INSERT INTO @InventoryIDList
VALUES
(123),
(456),
(789),
(111)
INSERT INTO @productsupplierIDList
VALUES
(999),
(888),
(777),
(666)
SELECT i.id, p.id
FROM @inventoryIDList i
INNER JOIN @productsupplierIDList p
oN i.joiningid = p.JoiningID