Linq의 목록에서 여러 필드 선택


128

ASP.NET C #에는 구조체가 있습니다.

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

그 목록이 있습니다. 내가 선택하려는 category_idcategory_name실행, DISTINCT그리고 마지막으로 ORDERBY에를 category_name.

여기 내가 지금 가진 것입니다 :

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

이것은 분명히 카테고리 이름을 얻습니다. 내 질문은 여러 필드를 어떻게 구할 수 있으며 어떤 데이터 구조를 (가 아닌 string[]) 에 저장 합니까?

편집하다

구조체 목록을 사용하는 것은 돌로 설정되어 있지 않습니다. 선택하기 쉽도록 백업 데이터 구조를 변경하는 것이 좋습니다 (많은 글을 쓸 것입니다).


10
는 LINQ 측에 관련되지 않은 동안, 나는 것이 강력하게 변경할 수 구조체 또는 공용 필드를 사용 할 수 없습니다 좋습니다. 개인적으로 나는 처음에는 구조체를 거의 만들지 않지만 가변 구조체는 문제를 요구하고 있습니다.
Jon Skeet

@ Jon Skeet 감사합니다. 개인 멤버와 함께 일반 클래스로 변환하겠습니다.
Chet

1
@Midhat : 가변 구조체는 사람들이 예상 한대로 동작하지 않기 때문에 모든 종류의 문제를 일으 킵니다. 그리고 공공 장은 캡슐화가 완전히 이루어지지 않습니다.
Jon Skeet

@ 존 스케 트. 변경 가능한 구조체의 함정에 대해 더 구체적으로 설명하거나 독서를 가리킬 수 있습니까?
Midhat

2
@Midhat : stackoverflow.com/questions/441309/why-are-mutable-structs-evil 에서 시작점을 살펴보십시오 .
Jon Skeet

답변:


228

익명 형식을 사용하면 나중에 코드에서 강력하게 형식화 된 데이터 구조로 임의의 필드를 선택할 수 있습니다.

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();

1 열에서 distinct를 사용하고 여러 열을 검색하고 싶습니다. 어떻게 할 수 있습니까?
Kishan Gajjar

1
나는 Select새로운 유형으로 생각하지 않았습니다 . 제 경우에는 새로운 것을 선택했습니다 KeyValuePair.
cjbarth

26
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로 만들었습니다!


하하, 고마워, 나는 도움을 주셔서 감사합니다. 분명히 이것은 세상에서 가장 어려운 질문이 아니 었습니다.
Chet

@IRBMe 실례합니다, 작은 질문입니다. 정확히 '가치'는 무엇입니까?
Fernando S. Kroes

23

익명 유형을 사용할 수 있습니다.

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

컴파일러와 클래스에 대한 코드 생성 namecategory_name해당 클래스의 속성과 반환 인스턴스를. 속성 이름을 수동으로 지정할 수도 있습니다.

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

임의의 수의 속성을 가질 수 있습니다.


6

다양한 예에서 위와 같이 linq Select를 사용하여 여러 필드를 선택할 수 있으며 이는 익명 유형으로 반환됩니다. 이 익명 유형을 피하려면 간단한 트릭이 있습니다.

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

나는 이것이 당신의 문제를 해결한다고 생각합니다.


5

이하는 일이다 익명 형식이 매우 적합하다. 사용법에서 유추하여 컴파일러가 자동으로 생성 한 유형의 객체를 반환 할 수 있습니다.

구문은 다음과 같은 형식입니다.

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();

4
var result = listObject.Select( i => new{ i.category_name, i.category_id } )

익명 형식을 사용하므로 식의 결과 형식을 미리 알 수 없으므로 var 키워드를 사용해야합니다.


3
(from i in list
 select new { i.category_id, i.category_name })
 .Distinct()
 .OrderBy(i => i.category_name);

3

KeyValuePair로 만들 수 있으므로 "IEnumerable<KeyValuePair<string, string>>"

따라서 다음과 같습니다.

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name )).Distinct();

이것은 이익없이 불필요한 복잡성을 추가합니다
Matze

2
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);
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.