C # Danh sách các đối tượng, làm thế nào để tôi có được tổng của một tài sản


158

Tôi có một danh sách các đối tượng. Một thuộc tính của mục nhập đối tượng cá nhân là số tiền. Làm thế nào để tôi có được tổng số tiền?

Nếu danh sách của tôi là loại gấp đôi, tôi có thể làm điều gì đó như thế này:

double total = myList.Sum();

Tuy nhiên tôi muốn một cái gì đó tương tự như thế này, nhưng cú pháp này không chính xác.

double total = myList.amount.Sum();

Làm thế nào tôi nên đi về việc thực hiện điều này? Tôi rất thích sử dụng hàm Sum nếu có thể thay vì lặp qua và tính toán giá trị.

Câu trả lời:


310
using System.Linq;

...

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

12
Đây có phải là nhanh hơn so với foreach ra ngoài quan tâm?
Coops

4
Tôi cũng quan tâm đến câu hỏi của @ CodeBlend. Tính toán này sẽ nhanh hơn một vòng lặp for?
rex

23
@Coops - Để trả lời câu hỏi của bạn ... bằng cách sử dụng danh sách chứa 100.000 đối tượng, mỗi đối tượng có một thuộc tính của kiểu dữ liệu nhân đôi, tổng hợp thuộc tính 1.000 lần bằng cách sử dụng giải pháp ở trên (myList.Sum) mất 2,44 giây so với 0,98 giây khi sử dụng foreach . Thời gian trôi qua được đo bằng cách sử dụng lớp Đồng hồ bấm giờ cho chính xác. Do đó, foreach nhanh hơn gấp 2 lần so với sử dụng myList.Sum.
Joe Gayetty

36

Và nếu bạn cần làm điều đó với các mục phù hợp với một điều kiện cụ thể ...

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

11

Một cách khác:

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

5
Thay vì .Select(i => i.Moons).Sum()bạn có thể sử dụng.Sum(i => i.Moons)
Mason

1
@Mason, đúng và đó là cách Alex tiếp cận vấn đề trong câu trả lời trước đó của anh ấy, vì vậy tôi chỉ cung cấp một cách khác để làm điều tương tự.
hữu íchBee

1
À vâng, xin lỗi vì quan niệm sai lầm của tôi.
Mason

Tôi đánh giá cao rằng đây là một câu trả lời độc đáo, nhưng hiệu suất sẽ không bị ảnh hưởng?
Peter Lenjo

2

Dưới đây là mã ví dụ bạn có thể chạy để thực hiện kiểm tra như vậy:

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

Ví dụ tương tự cho đối tượng phức tạp là:

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; }
}

Kết quả của tôi với tối ưu hóa trình biên dịch là:

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

và cho bài kiểm tra thứ hai là:

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

có vẻ như LINQ thường chậm hơn foreach (...) nhưng điều kỳ lạ đối với tôi là foreach (...) dường như nhanh hơn so với vòng lặp.


2
để tham khảo trong tương lai, có một cái nhìn tại Stopwatchtrong System.Diagnosticsvì nó là một thời gian ghi hiệu suất cao. (Tôi đã không đánh giá thấp bạn btw)
Meirion Hughes

1
Không sử dụng DateTime.Nowđể đo lường. Nó có hiệu suất khủng khiếp vì nó luôn trở lại theo giờ địa phương. DateTime.UtcNownhanh hơn; tuy nhiên, nó vẫn không sử dụng độ phân giải cao như Stopwatchlớp.
Gyorgy Kőszeg

3
Điều này không trả lời câu hỏi.
Mark Pattison

Ok, cảm ơn vì tiền boa. Điểm số rất lặp lại nên tôi cho rằng độ phân giải như vậy là đủ
Puchacz

2
Trong khi ý định của bạn là tốt -Mark là đúng - bạn không trả lời rõ ràng câu hỏi. Tôi khuyên bạn nên thay đổi nó thành: "Đây là cách bạn có thể làm điều đó" và "Đây là hiệu suất cpu của từng tùy chọn". Ngoài ra về nguyên tắc nếu bạn mô tả phương pháp thử nghiệm của bạn, bạn cần - không hiển thị cho chúng tôi mã.
Meirion Hughes
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.