我有3个收集清单如下。
public static List<Thing> English = new List<Thing>
{
new Thing {ID = 1, Stuff = "one"},
new Thing {ID = 2, Stuff = "two"},
new Thing {ID = 3, Stuff = "three"}
};
public static List<Thing> Spanish = new List<Thing>
{
new Thing {ID = 1, Stuff = "uno"},
new Thing {ID = 2, Stuff = "dos"},
new Thing {ID = 3, Stuff = "tres"},
new Thing {ID = 4, Stuff = "cuatro"}
};
public static List<Thing> German = new List<Thing>
{
new Thing {ID = 1, Stuff = "eins"},
new Thing {ID = 2, Stuff = "zwei"},
new Thing {ID = 3, Stuff = "drei"}
};
在运行时期间,列表的长度可能会有所不同。例如,德语可能有5个值,英语有2个,西班牙语有1个。
我需要找到哪个列表具有最大值,并且需要以下面的格式获得输出。
Id English German Spanish
1 one eins uno
2 two zwei dos
3 three drei tres
4 cuatro
你能帮我解决一下吗?
答案 0 :(得分:6)
试试这个:
English.Select(t => new Tuple<Thing,int>(t, 1)).Concatenate(
German.Select(t => new Tuple<Thing,int>(t, 2)).Concatenate(
Spanish.Select(t => new Tuple<Thing,int>(t, 3))
)
).GroupBy(p => p.Item1.ID)
.Select(g => new {
Id = g.Key
, English = g.Where(t => t.Item2==1).Select(t => t.Item2.Stuff).SingleOrDefault()
, German = g.Where(t => t.Item2==2).Select(t => t.Item2.Stuff).SingleOrDefault()
, Spanish = g.Where(t => t.Item2==3).Select(t => t.Item2.Stuff).SingleOrDefault()
});
我们的想法是使用其收藏来源标记原始项目(英语为1
,德语为2
,西班牙语为3
,按ID对其进行分组,然后拉出使用我们在第一步中添加的标记的各种语言的详细信息。
答案 1 :(得分:1)
如果它们都从一个开始并且从不跳过任何数字(但可以在任何时候结束)那么你可以使用更简单的方法,例如:
int count = Math.Max(English.Count, Math.Max(Spanish.Count, German.Count));
var query = Enumerable.Range(0, count)
.Select(num => new
{
Id = num + 1,
English = GetValue(English, num),
Spanish = GetValue(Spanish, num),
German = GetValue(German, num),
});
如果可以跳过数字,或者不从1开始,那么你可以使用这种稍微复杂的方法:
var englishDic = English.ToDictionary(thing => thing.ID, thing => thing.Stuff);
var spanishDic = Spanish.ToDictionary(thing => thing.ID, thing => thing.Stuff);
var germanDic = German.ToDictionary(thing => thing.ID, thing => thing.Stuff);
var query = englishDic.Keys
.Union(spanishDic.Keys)
.Union(germanDic.Keys)
.Select(key => new
{
Id = key,
English = GetValue(englishDic, key),
Spanish = GetValue(spanishDic, key),
German = GetValue(germanDic, key),
});
需要一些辅助函数来避免无效的参数错误:
public static string GetValue(Dictionary<int, string> dictionary, int key)
{
string output;
if (dictionary.TryGetValue(key, out output))
return output;
else
return "";
}
public static string GetValue(List<Thing> list, int index)
{
if (index < list.Count)
return list[index].Stuff;
else
return "";
}
答案 2 :(得分:0)
这很有趣:)
我这样做了,但是,就像许多这些答案一样,效率不高:
public IEnumerable ListEmAll() {
return new List<int>() // just for balance, start with empty list
.Union( English.Select(o => o.ID) )
.Union( Spanish.Select(o => o.ID) )
.Union( German.Select(o => o.ID) )
.OrderBy(id => id)
.Select(id =>
new
{
ID = id,
English = English.Where(o => o.ID == id).Select(o => o.Stuff),
Spanish = Spanish.Where(o => o.ID == id).Select(o => o.Stuff),
German = German.Where(o => o.ID == id).Select(o => o.Stuff)
});
}
但我更喜欢的是不使用Linq,并返回一个复合词典......列表上没有昂贵的查找。
// keep a list of the languages for later
static Dictionary<string, List<Thing>> languages = new Dictionary<string, List<Thing>>(){
{"English", English},
{"Spanish", Spanish},
{"German", German}
};
// result[3]["English"] = "three"
public Dictionary<int, Dictionary<string, string>> ListEmAll_better() {
Dictionary<int, Dictionary<string, string>> result = new Dictionary<int, Dictionary<string, string>>();
foreach(var lang in languages.Keys) {
foreach(var thing in languages[lang]) {
if(!result.ContainsKey(thing.ID)) {
result[thing.ID] = new Dictionary<string, string>();
}
result[thing.ID][lang] = thing.Stuff;
}
}
return result;
}