C # 객체 목록, 속성의 합계를 얻는 방법


158

개체 목록이 있습니다. 개별 객체 항목의 한 속성은 금액입니다. 금액의 합계는 어떻게 얻습니까?

내 목록이 double 유형 인 경우 다음과 같은 작업을 수행 할 수 있습니다.

double total = myList.Sum();

그러나 이와 비슷한 것을 원하지만이 구문은 올바르지 않습니다.

double total = myList.amount.Sum();

이것을 달성하려면 어떻게해야합니까? 가능한 경우 루프 값을 계산하고 계산하는 대신 Sum 함수를 사용하고 싶습니다.

답변:


310
using System.Linq;

...

double total = myList.Sum(item => item.Amount);

12
이것은 관심을 끄는 것보다 빠릅니까?
— Coops

4
@CodeBlend의 질문에도 관심이 있습니다. 이 계산이 for 루프보다 빠를까요?
— rex

23
@Coops-질문에 대답하려면 100,000 개의 객체가 포함 된 목록을 사용하여 각 유형의 단일 데이터 유형 속성을 갖는 각 객체는 위의 솔루션 (myList.Sum)을 사용하여 속성을 1,000 번 합산하면 foreach를 사용하여 0.98 초에 비해 2.44 초가 걸립니다. . 경과 시간은 정확성을 위해 스톱워치 클래스를 사용하여 측정됩니다. 따라서 foreach는 myList.Sum을 사용하는 것보다 2 배 이상 빠릅니다.
— Joe Gayetty

36

특정 조건과 일치하는 항목에서 해야하는 경우 ...

double total = myList.Where(item => item.Name == "Eggs").Sum(item => item.Amount);

11

다른 대안 :

myPlanetsList.Select(i => i.Moons).Sum();

5
대신 .Select(i => i.Moons).Sum()사용할 수 있습니다.Sum(i => i.Moons)
— Mason

1
@Mason은 알렉스가 이전 답변에서 문제에 접근 한 방식이므로 동일한 작업을 수행하는 다른 방법을 제공했습니다.
— 유용한 Bee

1
아 네, 오해해서 미안합니다.
— Mason

이 답변이 고유하지만 성능이 저하되지 않습니까?
— 피터 렌조

2

이러한 테스트를하기 위해 실행할 수있는 예제 코드는 다음과 같습니다.

var f = 10000000;
var p = new int[f];

for(int i = 0; i < f; ++i)
{
    p[i] = i % 2;
}

var time = DateTime.Now;
p.Sum();
Console.WriteLine(DateTime.Now - time);

int x = 0;
time = DateTime.Now;
foreach(var item in p){
   x += item;
}
Console.WriteLine(DateTime.Now - time);

x = 0;
time = DateTime.Now;
for(int i = 0, j = f; i < j; ++i){
   x += p[i];
}
Console.WriteLine(DateTime.Now - time);

복잡한 객체의 동일한 예는 다음과 같습니다.

void Main()
{
    var f = 10000000;
    var p = new Test[f];

    for(int i = 0; i < f; ++i)
    {
        p[i] = new Test();
        p[i].Property = i % 2;
    }

    var time = DateTime.Now;
    p.Sum(k => k.Property);
    Console.WriteLine(DateTime.Now - time);

    int x = 0;
    time = DateTime.Now;
    foreach(var item in p){
        x += item.Property;
    }
    Console.WriteLine(DateTime.Now - time);

    x = 0;
    time = DateTime.Now;
    for(int i = 0, j = f; i < j; ++i){
        x += p[i].Property;
    }
    Console.WriteLine(DateTime.Now - time);
}

class Test
{
    public int Property { get; set; }
}

컴파일러 최적화를 해제 한 결과는 다음과 같습니다.

00:00:00.0570370 : Sum()
00:00:00.0250180 : Foreach()
00:00:00.0430272 : For(...)

두 번째 테스트는 다음과 같습니다.

00:00:00.1450955 : Sum()
00:00:00.0650430 : Foreach()
00:00:00.0690510 : For()

LINQ가 일반적으로 foreach (...)보다 느린 것처럼 보이지만 이상한 점은 foreach (...)가 for 루프보다 빠르다는 것입니다.


2
향후 참조를 위해, 한 번 봐 가지고 Stopwatch있는 System.Diagnostics이 고성능 시간 레코더로합니다. (내가 BTW 당신을 downvote하지 않았다)
— Meirion 휴즈에게

1
DateTime.Now측정 에는 사용하지 마십시오 . 항상 현지 시간을 반환하므로 성능이 끔찍합니다. DateTime.UtcNow가 더 빠르다; 그러나 여전히 Stopwatch클래스 만큼 높은 해상도를 사용하지는 않습니다 .
— György Kőszeg

3
이것은 질문에 대답하지 않습니다.
— 마크 패티 슨

알았어, 팁 고마워 점수는 매우 반복적이므로 그러한 해결책이 충분하다고 생각했습니다
— Puchacz

2
당신의 의도는 좋지만 마크는 옳습니다. 당신은 그 질문에 명시 적으로 대답하지 않습니다. "여기서 수행 할 수있는 방법은 다음과 같습니다"및 "각 옵션의 CPU 성능은 다음과 같습니다"로 변경하는 것이 좋습니다. 또한 원칙적으로 테스트 방법을 설명하면 코드를 보여줄 필요가 없습니다.
— Meirion Hughes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.