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

If they all start at one and never skip any numbers (but can end at any point) then you can use a more simple approach, such as this:

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),
    });

If it's possible for numbers to be skipped, or not start at one, then you could use this slightly more complex approach:

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),
        });

A few helper functions were needed to avoid invalid argument errors:

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 に答える