7

オブジェクトをペアに分割するために使用できるプロパティを持つオブジェクトのリストがあります。各オブジェクトがペアの一部であることを事前に知っています。

状況を説明する例を次に示します。


ペアにまとめたい靴のリストがあります。

私のリストが次のようになっているとしましょう:

List<Shoe> shoes = new List<Shoe>();

shoes.Add(new Shoe { Id = 19, Brand = "Nike", LeftOrRight = LeftOrRight.L });
shoes.Add(new Shoe { Id = 29, Brand = "Nike", LeftOrRight = LeftOrRight.R });
shoes.Add(new Shoe { Id = 11, Brand = "Nike", LeftOrRight = LeftOrRight.L });
shoes.Add(new Shoe { Id = 60, Brand = "Nike", LeftOrRight = LeftOrRight.R });
shoes.Add(new Shoe { Id = 65, Brand = "Asics", LeftOrRight = LeftOrRight.L });
shoes.Add(new Shoe { Id = 82, Brand = "Asics", LeftOrRight = LeftOrRight.R });

次のように、これらの靴をペアで出力したいと思います。

ペア:
Id:19、ブランド:Nike、LeftOrRight:L
Id:29、ブランド:Nike、LeftOrRight:R

ペア:
Id:11、ブランド:Nike、LeftOrRight:L
Id:60、ブランド:Nike、LeftOrRight:R

ペア:
Id:65、ブランド:Asics、LeftOrRight:L
Id:82、ブランド:Asics、LeftOrRight:R

個々の靴は、単一のペアの一部としてのみ存在できることに注意してください。

靴をグループ化するために次のコードを試しましたが、明らかにペアが欠落しています。

var pairsByBrand = shoes.GroupBy(s => s.Brand);
foreach (var group in pairsByBrand)
{
    Console.WriteLine("Pair:");
    foreach (var shoe in group)
    {
        Console.WriteLine(shoe);
    }
    Console.WriteLine();
}

これらのアイテムをペアにグループ化するために使用できるステートメントは何ですか?

4

3 に答える 3

9

SelectManyとを使用して、 sのZipを生成する純粋な機能LINQ :IEnumerableTuple

IEnumerable<Tuple<Shoe, Shoe>> pairs = shoes
    .GroupBy(shoe => shoe.Brand)
    .SelectMany(brand=>
        Enumerable.Zip(
            brand.Where(shoe=>shoe.LeftOrRight == LeftOrRight.L),
            brand.Where(shoe=>shoe.LeftOrRight == LeftOrRight.R),
            Tuple.Create
        )
    );
于 2012-09-07T15:20:57.693 に答える
3
var shoesByBrand = shoes.GroupBy(s => s.Brand);
foreach (var byBrand in shoesByBrand)
{
    var lefts = byBrand.Where(s => s.LeftOrRight == LeftOrRight.L);
    var rights = byBrand.Where(s => s.LeftOrRight == LeftOrRight.R);
    var pairs = lefts.Zip(rights,(l, r) => new {Left = l, Right = r});

    foreach(var p in pairs)
    {
        Console.WriteLine("Pair:  {{{0}, {1}}}", p.Left.Id, p.Right.Id);
    }

    Console.WriteLine();
}

注:Zipは可能な限りペアリングするだけです。追加の権利または左権がある場合、それらは報告されません。

于 2012-09-07T15:13:53.910 に答える
2

それを行う1つの方法:

var pairs = shoes.GroupBy(s => s.Brand)
                 .Select(g => g.GroupBy(s => s.LeftOrRight));
                 .SelectMany(Enumerable.Zip(g => g.First(), g => g.Last(),Tuple.Create));

これは、コレクションを1回だけ繰り返すことで、靴のブランドごとに左右の靴に分割するという点で、私の最初のアイデア( Thom Smithによってうまく実装されている)の改善である可能性があります。靴がたくさんあるブランドがあればもっと速くなるはずだという直感があります。

靴をブランドごとにグループ化し、次に各ブランド内で左/右ごとにグループ化します。次に、各ブランドの左の靴と同じブランドの右の靴をランダムに一致させ、すべてのブランドに対して順番に一致させます。

于 2012-09-07T15:23:49.823 に答える