0

私は持っていList<Item>ます。Itemプロパティ、、IdNameありAmountます。このリストには重複するアイテムがあります。複製されていないsList<Item>のみを含む新しいものを取得する必要があります。 'sは、最初に複製された回数の量である必要があります。私は次のようなことを試みましたItemItemAmountList<Item>

            for (int i = 0; i < list.Count; i++)
            {
                for (int j = 0; j < list.Count; j++)
                {
                        if (list[i].Name == list[j].Name)
                        {
                            list.Remove(prod.Components[j]);
                            list[i].Amount++;
                        }
                }
            }

しかし、このループにはいくつかの問題があります。私の脳は過熱しています。助けてください。

4

5 に答える 5

1

単純なLINQクエリを使用すると、一意のアイテムとそれらが表示される回数を取得できます。

var distinct = list.GroupBy(o => o.Name)
                   .Select(g => new { Count = g.Count(), Item = g.First() })
                   .ToList();

次に、各アイテムAmountを重複の数に変更できます。

foreach (var row in distinct)
{
    row.Item.Amount = row.Count;
}

そして最後にList<Item>、重複がなく、正しい金額のを取り戻します。

var uniqueItems = distinct.Select(r => r.Item).ToList();

重要:上記のコードは、「重複する」アイテムが互いに区別できないことを前提としていますが、それ以外は何も想定していません(たとえばItem、デフォルトのコンストラクターは必要ありません)。詳細によっては、さらに短い形式で書くことができる場合があります。

さらに、Amountプロパティはここで奇妙に見えます。重複はそれらの金額の合計を保証しないので、目的はItem.Amount何ですか?量が2の重複アイテムは、量が4の1つのアイテムになると思いますが、コードはそれを行いません(そして私のコードはそのリードに従います)。

于 2013-02-20T10:45:17.767 に答える
0

そのようなことを試してください:

var groups = from item in items
             group item by item.Property
             into grouped
             select grouped;

var distinct = from g in groups
               let item = g.First()
               let amount = g.Count()
               select new Item {Property = item.Property, Amount = amount};

その後、元のアイテムリストからの金額がdistinct含まれます。IEnumerable<Item>

于 2013-02-20T10:52:25.487 に答える
0

ID最初の2つのプロパティとによって重複を判別するとしますName

を実装して、次のIEqualityComparer<Item>目的で使用できEnumerable.GroupByます。

var itemAmounts = items.GroupBy(i => i, new Item())
    .Select(g => new Item { 
        ID = g.First().ID, 
        Name = g.First().Name, 
        Amount = g.Count()
    });

これが、意味のある実装を持つItemクラスですIEqualityComparer<Item>

class Item : IEqualityComparer<Item>
{
    public int ID;
    public string Name;
    public int Amount;

    public bool Equals(Item x, Item y)
    {
        if (x == null || y == null) return false;

        bool equals = x.ID == y.ID && x.Name == y.Name;
        return equals;
    }

    public int GetHashCode(Item obj)
    {
        if (obj == null) return int.MinValue;

        int hash = 19;
        hash = hash + obj.ID.GetHashCode();
        hash = hash + obj.Name.GetHashCode();
        return hash;
    }
}

Equalsまた、GetHasdhCodeからをオーバーライドすることもできobjectます。そうすれば、カスタム比較機能はまったく必要ありませんGroupBy

var itemAmounts = items.GroupBy(i => i)
    .Select(g => new Item { 
        ID = g.First().ID, 
        Name = g.First().Name, 
        Amount = g.Count()
    });

上記のすでに利用可能な方法を使用できます。

public override bool Equals(object obj)
{
    Item item2 = obj as Item;
    if (item2 == null)
        return false;
    else
        return Equals(this, item2);
}

public override int GetHashCode()
{
    return GetHashCode(this);
}
于 2013-02-20T10:53:29.273 に答える
0
foreach(var item in list)
{
    if(list.Count(e=>e.Id == item.Id && e.Name == item.Name)!=1)
    {
        list.Remove(item);
    }
}
于 2013-02-20T10:53:32.443 に答える
0

私の頭のてっぺんから(それをテストしていません):

list.GroupBy(x => x.Name)
    .Select(x => new Item {
                            Name = x.Key,
                            Amount = x.Count()
                          })
    .ToList();

IDがどうなるかを指定していないので、無視しておきます。

(これにより、元のリストが変更されるのではなく、新しいリストが作成されることに注意してください)。

于 2013-02-20T10:44:43.973 に答える