4

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

你能帮我解决这个问题吗?

4

3 回答 3

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 对它们进行分组,然后使用我们在第一步中添加的标签提取各个语言的详细信息。

于 2012-10-22T16:46:34.217 回答
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),
    });

如果可以跳过数字或不从一个开始,那么您可以使用这种稍微复杂的方法:

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 "";
}
于 2012-10-22T16:56:05.240 回答
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;
}
于 2012-10-22T21:35:47.807 回答