2010-08-25 34 views

Trả lời

23

Chỉ cần hình dung nó ra bản thân mình ...

Phương pháp IEnumerable<T>.Where() có quá tải mà sẽ đưa các chỉ số của phần tử hiện tại - chỉ là những gì bác sĩ đã ra lệnh.

(new []{1,2,3,4,5}).Where((elem, idx) => idx % 2 == 0); 

này sẽ quay trở lại

{1, 3, 5} 

Cập nhật: Để bao gồm cả trường hợp sử dụng của tôi và đề nghị Dan Tao, chúng ta hãy cũng xác định những yếu tố trở lại đầu tiên nên là:

var firstIdx = 1; 
var takeEvery = 2; 
var list = new []{1,2,3,4,5}; 

var newList = list 
    .Skip(firstIdx) 
    .Where((elem, idx) => idx % takeEvery == 0); 

... sẽ trả lại

{2, 4} 
+2

Lần đầu tiên tôi nhìn thấy một cách sử dụng thực sự vững chắc cho chỉ mục trong một thuộc tính tập hợp, bravo, tôi sẽ không nghĩ điều này. –

+0

Bạn có thể xác định phương thức mở rộng sẽ trả về giá trị này.Đây (...) để làm cho điều này rõ ràng hơn trong chính ứng dụng của bạn. – Douglas

+5

Tôi có thể đề xuất sử dụng 'idx + 1' để khớp với mô tả của" mọi phần tử Nth "; ít nhất với tôi, điều này gợi ý rằng phần tử đầu tiên được trả về phải là phần tử thứ N. Vì vậy, mỗi phần tử thứ 2 trong '{1,2,3,4,5}' - thành * me * - có nghĩa là '{2,4}' (mã của bạn trả về '{1,3,5}'). Có lẽ đây là chủ quan, mặc dù. –

8

Thực hiện Cristi's suggestion:

public static IEnumerable<T> Sample<T>(this IEnumerable<T> source, int interval) 
{ 
    // null check, out of range check go here 

    return source.Where((value, index) => (index + 1) % interval == 0); 
} 

Cách sử dụng:

var upToTen = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

var evens = upToTen.Sample(2); 
var multiplesOfThree = upToTen.Sample(3); 
+0

Bạn cũng có thể bỏ qua mảng và sử dụng 'Enumerable.Range (1,10)'. –

+2

@Anthony: Đây chỉ là một ví dụ, nhằm mục đích hiểu ngay lập tức. Tôi biết một số nhà phát triển sẽ phải tra cứu 'Enumerable.Range'. –

0

Trong khi không phải LINQ bạn cũng có thể tạo ra một phương pháp khuyến nông với yield.

public static IEnumerable<T> EverySecondObject<T>(this IEnumerable<T> list) 
{ 
    using (var enumerator = list.GetEnumerator()) 
    { 
     while (true) 
     { 
      if (!enumerator.MoveNext()) 
       yield break; 
      if (enumerator.MoveNext()) 
       yield return enumerator.Current; 
      else 
       yield break; 
     } 
    } 
} 
+2

Quấn điều đó trong một 'sử dụng'! ('IEnumerable' kế thừa' IDisposable'.) –

+0

@Dan: Bạn có nghĩa là IEnumerator. Sao tôi chưa bao giờ nhận ra điều đó trước đây?

+0

Vâng, tôi có nghĩa là 'IEnumerator'. Rất tiếc! (Vì một lý do nào đó, tôi luôn gõ một khi tôi muốn gõ cái kia. Phải là bộ nhớ cơ.) –

Các vấn đề liên quan