3

(これはキー (この場合は , ) のように使用されますIEnumerable<IEnumerable<CustomObject>>)とCustomObject値があります。いくつかのふりデータ:x123y

{
  { {1, 2}, {2, 4}, {3, 6}, {4, 8} }, 
  { {1, 2}, {2, 0}, {3, 0}, {4,-2} },
  { {1, 2}, {2, 2}, {3, 0}, {4, 0} }
}

以下を取得できる最良の方法は何ですかIEnumerable<CustomObject>:

{ {1, 2}, {2, 2}, {3, 2}, {4, 2} }

yつまり、各要素の値の平均です。

パフォーマンスは合理的である必要があるため、no.ToList()または類似のものは使用できません。LINQでいろいろ試してみましたがだめでした。

アップデート

@Bort、@Rawling、私はあなたの答えをテストしましたが、@Rawling の方がわずかに高速です。ただし、@Bortの答えはより読みやすいので、当面はそれで行くと思います。お気軽に回答をお待ちしております!

4

4 に答える 4

5

LINQ を使用すると、リストのリストをSelectMany、次にGroupByx Select、平均で平坦化できます。

var averages = customObjectLists
    .SelectMany(l => l)
    .GroupBy(co => co.x)
    .Select(g => new CustomObject { x => g.Key, y = g.Average(co => co.y) });
于 2012-08-09T13:19:58.967 に答える
1

外側の列挙子を固定しても構わない場合は、次の LINQy メソッドで内側の列挙子の実行を延期します。

IEnumerable<V> AggregateAcross<T, U, V>(
            IEnumerable<IEnumerable<T>> input,
            Func<T, U> select,
            Func<IEnumerable<U>, V> aggregate)
    {
        var enumerators = input.Select(ie => ie.GetEnumerator()).ToArray();
        while (enumerators.All(e => e.MoveNext()))
        {
            yield return aggregate(enumerators.Select(e => select(e.Current)));
        }
    }

例として呼び出す

foreach (var avg in AggregateAcross(
                     input,
                     pair => pair.y,
                     e => e.Average(y => y)))
{
    Console.WriteLine(avg);
}

これは、内側の列挙子の 1 つが要素を使い果たすとすぐに停止することに注意してください。また、完了したらすべての列挙子を破棄する必要があります。さらなるアイデアについては、この回答をご覧ください。

(これは値を完全に無視していることにも注意してxください。すべての入力が適切であり、目的の出力も適切であるため、x値は何も追加しません。)

于 2012-08-09T13:35:31.420 に答える
1

このようなもので、探している結果が得られるはずです。リストのリストを単一の にフラット化し、値でList<CustomObject>グループ化し、X値を平均して、プロパティを持つ匿名型の をY残します。のコンストラクターを呼び出すように を変更すると、.IEnumerableXYselect new {} ...CustomObjectIEnumerable<CustomObject>

var myComplexObject = //your IEnumerable<IEnumerable<CustomObject>>
var result = from firstList in myComplexObject
        from secondList in firstList
        group secondList by secondList.X into grp
        select new {X = grp.Key, Y = (int)grp.Average(p=>p.Y)};
于 2012-08-09T13:17:16.240 に答える
-1

私はそれをテストしませんでしたが、これはうまくいくはずだと思います。

public void Test() {
    IEnumerable<IEnumerable<CustomObject>> data = ...;
    var result = data
        .SelectMany(x => x)
        .GroupBy(
            item => item.x,
            (key, r) => new { x = key, data = r.Select(z => z.y) }
        )
        .Select(x => new CustomObject { x = x.x, y = (int)x.data.Average() })
        .ToList();
}
于 2012-08-09T13:14:05.423 に答える