1

自分のクラス「Vertrag」(「契約」) のインスタンスのリストがあり、それらをグループ化する必要があります。

単純な GroupBy はまさに私が必要とすることを行います: 最後の 4 つのフィールドでグループ化すると、結果は IEnumerable<IGrouping<...,Vertrag>> になります。この結果タイプを使用できます。反復処理は簡単です。
... とマークされた場所では、型定義として何も与えられていません。これは匿名型のようですか?

さらにリクエストがありました。最大値があることを確認してください。各グループの 3 つの要素。すべてが割り当てられるまで、新しいグループを開始します (キーは同じです!)。StackOverflow でもその解決策を見つけました。LINQ はもう少し複雑ですが、正常に動作しています。戻り値の型だけがやや複雑です。
この複雑な構造を単純な IGrouping フォームに変換して、既存のコードで動作するようにしたいと考えています。

私はそれをほぼ機能させるか、少なくとも単純な GroupBy と同じくらい使いやすいバージョンに単純化しましたが、まったく同じではありません。元のグループ化に従ってコードを変更する必要がないように、この IGrouping を匿名型で自分で作成する方法はありますか?

キーは、GroupBy が意味することとは正反対に、同じものを複数回出てきます。したがって、手作りの IGrouping でそれが可能になるかどうかはわかりません。

これは、動作する LINQPad の例です (型定義付き):

void Main() 
{
    List<Vertrag> verträge = new List<Vertrag>();
    verträge.Add(new Vertrag("a1","b1","c","d","e"));
    verträge.Add(new Vertrag("a2","b1","c","d","e"));
    verträge.Add(new Vertrag("a3","b1","c","d","e"));
    verträge.Add(new Vertrag("a4","b1","c","d","e"));
    verträge.Add(new Vertrag("a5","b1","c","d","e"));
    verträge.Add(new Vertrag("a6","b1","c","d","e"));
    verträge.Add(new Vertrag("a7","b1","c","d","e"));
    verträge.Add(new Vertrag("a1","b2","c","d","e"));
    verträge.Add(new Vertrag("a2","b2","c","d","e"));
    verträge.Add(new Vertrag("a3","b2","c","d","e"));
    verträge.Add(new Vertrag("a4","b2","c","d","e"));

    // Very easy first group
    var verträgeGruppiert = verträge
        .GroupBy(v => new { v.Beginn, v.Ende, v.Vorlage, v.Ware });
    verträgeGruppiert.Dump();

    // Far more complex grouping
    var maxInGroup = 3;
    var verträgeGruppiertMax = verträge
        .GroupBy(v => new {v.Beginn, v.Ende, v.Vorlage, v.Ware})
        .Select(g => new 
            {
                Key = g.Key, 
                Teile = g.Select((v,i) => new {Value = v, Index = i})
                    .GroupBy(item => item.Index / maxInGroup)
            });
    verträgeGruppiertMax.Dump();

    // Transform back into simpler style
    // SelectMany used instead select, see comment in question
    var vereinfacht = verträgeGruppiertMax
        .SelectMany(vgm => vgm.Teile
            .Select(t => new 
                { 
                    vgm.Key, 
                    a = t.Select(x => x.Value.ID)
                }));
    vereinfacht.Dump();
}

public class Vertrag 
{
    public Vertrag( // Constructor
        string id,
        string beginn,
        string ende,
        string vorlage,
        string ware)
    {
        ID = id;
        Beginn = beginn;
        Ende = ende;
        Vorlage = vorlage;
        Ware = ware;
    }

    // Fields
    public string ID { get; private set; }
    public string Beginn { get; private set; }
    public string Ende { get; private set; }
    public string Vorlage { get; private set; }
    public string Ware { get; private set; }
}
4

1 に答える 1

0

独自の目的の動作で IGrouping を実装するだけです。これにより、コードがはるかに簡単になります。

「アプリケーション」:

var elements = new List<Tuple<string, string, string, string>>();
elements.Add(Tuple.Create("a", "one", "A1", "Banana"));
elements.Add(Tuple.Create("a", "two", "B3", "Orange"));
elements.Add(Tuple.Create("a", "three", "C5", "Kiwi"));
elements.Add(Tuple.Create("a", "four", "D7", "Coconut"));
elements.Add(Tuple.Create("a", "five", "E9", "Maracuja"));
elements.Add(Tuple.Create("b", "one", "A1", "Banana"));
elements.Add(Tuple.Create("b", "two", "B3", "Orange"));
elements.Add(Tuple.Create("b", "three", "C5", "Kiwi"));
elements.Add(Tuple.Create("b", "four", "D7", "Coconut"));
elements.Add(Tuple.Create("b", "five", "E9", "Maracuja"));

var groups = elements.GroupBy(element => element.Item1);
var cuttedGroups = groups.Select(group => CuttedGroup.Create(group, 3));

foreach (var group in cuttedGroups)
{
    foreach (var item in group)
    {
        Console.WriteLine(item);
    }

    Console.WriteLine();
}

CuttedGroup の実装:

public static class CuttedGroup
{
    public static IGrouping<TKey, TElement> Create<TKey, TElement>(IGrouping<TKey, TElement> source, int maximumElements)
    {
        return new CuttedGroup<TKey, TElement>(source, maximumElements);
    }
}

public class CuttedGroup<TKey, TElement> : IGrouping<TKey, TElement>
{
    private IGrouping<TKey, TElement> _Source;
    private int _MaximumElements;

    public CuttedGroup(IGrouping<TKey, TElement> source, int maximumElements)
    {
        // Parameter check omitted...

        _Source = source;
        _MaximumElements = maximumElements;
    }
    public TKey Key
    {
        get { return _Source.Key; }
    }

    public IEnumerator<TElement> GetEnumerator()
    {
        return _Source.Take(_MaximumElements).GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
于 2014-10-23T13:53:40.050 に答える