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.