web-dev-qa-db-ja.com

テーブルの1つのフィールドのみに基づいたLinqで異なる

私は、テーブルの1つのフィールドに基づいて結果を取得するために、Linqで.distinctを使用しようとしています(したがって、テーブルから重複するレコード全体を必要としません)。

私は次のようにdistinctを使用して基本的なクエリを書くことを知っています:

var query = (from r in table1
orderby r.Text
select r).distinct();

しかし、r.textが重複していない結果が必要です。

102
Megha Jain

これを試して:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());

これは、テーブルをTextでグループ化し、各グループの最初の行を使用して、Textが異なる行になります。

248
Daniel Hilgarth

MoreLinqには、使用可能な DistinctBy メソッドがあります。

次のことが可能になります。

var results = table1.DistictBy(row => row.Text);

メソッドの実装(引数検証の省略)は次のとおりです。

private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}
18
Servy

しかし、r.textが複製されない結果が必要です

これが欲しいかのように聞こえます:

table1.GroupBy(x => x.Text)
      .Where(g => g.Count() == 1)
      .Select(g => g.First());

これにより、Textが一意の行が選択されます。

11
Tim Schmelter

このトピックについては多くの議論があります。

それらの1つを見つけることができます here

最も一般的な提案の1つは、@ Servyが指摘したように、ラムダ式をパラメーターとして使用するDistinctメソッドです。

C#のチーフアーキテクトであるAnders Hejlsbergは、解決策を提案しました ここ 。また、フレームワーク設計チームがラムダを使用するDistinctメソッドのオーバーロードを追加しないことにした理由を説明します。

3
TKharaishvili

Daniel Hilgarth の上記の回答は、Entity-FrameworkSystem.NotSupported例外につながります。 Entity-Frameworkでは、次のようにする必要があります。

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());
3
Biraj Saha

私が見つけたものから、あなたのクエリはほとんど正しいです。 「select r」を「select r.Text」に変更するだけで問題は解決します。これは、MSDNがどのように機能するかを文書化した方法です。

例:

    var query = (from r in table1 orderby r.Text select r.Text).distinct();
2
Josh Parks
data.Select(x=>x.Name).Distinct().Select(x => new SelectListItem { Text = x });
1
bgS