web-dev-qa-db-ja.com

Linqのリストから複数のフィールドを選択する

ASP.NET C#では、構造体があります:

public struct Data
{
    public int item1;
    public int item2;
    public int category_id;
    public string category_name;
}

そして私はそれらのリストを持っています。 category_idcategory_nameを選択して、DISTINCTを実行し、最後にcategory_nameORDERBYを実行します。

私が今持っているものは次のとおりです。

List<Data> listObject = getData();
string[] catNames = listObject
                    .Select(i=> i.category_name)
                    .Distinct()
                    .OrderByDescending(s => s)
                    .ToArray();

これは明らかにカテゴリ名を取得するだけです。私の質問は、どうすれば複数のフィールドを取得でき、どのデータ構造を(string[]ではなく)格納するのでしょうか?

編集

構造体のリストを使用することは明確ではありません。選択を容易にするためにバッキングデータ構造を変更することをお勧めします(これらの多くを書く予定です)場合は、お勧めします。

119
Chet

匿名型を使用すると、任意のフィールドを選択して、後でコードで強く型付けされるデータ構造に含めることができます。

var cats = listObject
    .Select(i => new { i.category_id, i.category_name })
    .Distinct()
    .OrderByDescending(i => i.category_name)
    .ToArray();

後で使用するために(明らかに)保存する必要があるため、GroupBy演算子を使用できます。

Data[] cats = listObject
    .GroupBy(i => new { i.category_id, i.category_name })
    .OrderByDescending(g => g.Key.category_name)
    .Select(g => g.First())
    .ToArray();
209
Jason
var selectedCategories =
    from value in
        (from data in listObject
        orderby data.category_name descending
        select new { ID = data.category_id, Name = data.category_name })
    group value by value.Name into g
    select g.First();

foreach (var category in selectedCategories) Console.WriteLine(category);

編集:もっとLINQ-eyに!

23
IRBMe

匿名タイプを使用できます。

.Select(i => new { i.name, i.category_name })

コンパイラは、nameおよびcategory_nameプロパティを持つクラスのコードを生成し、そのクラスのインスタンスを返します。プロパティ名を手動で指定することもできます。

i => new { Id = i.category_id, Name = i.category_name }

任意の数のプロパティを設定できます。

22
Mehrdad Afshari

これは、 anonymous types が非常に適しているタスクです。使用法から推測される、コンパイラーによって自動的に作成されるタイプのオブジェクトを返すことができます。

構文は次の形式です。

new { Property1 = value1, Property2 = value2, ... }

あなたの場合、次のようなものを試してください:

var listObject = getData();
var catNames = listObject.Select(i =>
    new { CatName = i.category_name, Item1 = i.item1, Item2 = i.item2 })
    .Distinct().OrderByDescending(s => s).ToArray();
5
Noldorin

KeyValuePairにすることができるため、"IEnumerable<KeyValuePair<string, string>>"を返します

したがって、次のようになります。

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name )).Distinct();
4
Victor
var result = listObject.Select( i => new{ i.category_name, i.category_id } )

これは匿名型を使用するため、式の結果の型は事前にわからないため、varキーワードを使用する必要があります。

4
Paul van Brenk
(from i in list
 select new { i.category_id, i.category_name })
 .Distinct()
 .OrderBy(i => i.category_name);
3
Joe Chung

上記のさまざまな例で示されているように、linq Selectを使用して複数のフィールドを選択できます。これにより、匿名タイプとして返​​されます。この匿名型を避けたい場合は、ここに簡単なトリックがあります。

var items = listObject.Select(f => new List<int>() { f.Item1, f.Item2 }).SelectMany(item => item).Distinct();

これで問題が解決すると思います

2
AR M
public class Student
{
    public string Name { set; get; }
    public int ID { set; get; }
}

class Program
{
  static void Main(string[] args)
    {
        Student[] students =
        {
        new Student { Name="zoyeb" , ID=1},
        new Student { Name="Siddiq" , ID=2},
        new Student { Name="sam" , ID=3},
        new Student { Name="james" , ID=4},
        new Student { Name="sonia" , ID=5}
        };

        var studentCollection = from s in students select new { s.ID , s.Name};

        foreach (var student in studentCollection)
        {
            Console.WriteLine(student.Name);
            Console.WriteLine(student.ID);
        }
    }
}
0
Zoyeb Shaikh