2017-07-07 94 views
5

我已經習慣了使用Java的Stream#Peek方法,因爲它是調試中間流操作的有用方法。對於那些你們誰不熟悉Stream#Peek方法,下面顯示了它的定義:在Linq C#中Java的Stream#Peek方法等價於什麼?

Stream<T> peek(Consumer<? super T> action)

返回由該流的要素流, 還執行提供行動在每個元素上作爲 元素從結果流中消耗。這是一個 中間操作。

考慮下面這個簡單的例子:

List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); 
List<Integer> result = integerList.stream() 
            .filter(i -> i % 2 == 0) 
            .peek(System.out::println) 
            .collect(Collectors.toList()); 

隨着Stream#Peek方法,這應該基本上允許我向所有的偶數打印到控制檯,這樣我可以測試,看看那是什麼我會期待的。

我試圖找到答案手頭上的問題,但似乎無法找到C#類似的方法,沒有人知道相當於Java的Stream#Peek或其他方法有類似的行爲?

+0

List類上有ForEach方法(對於IEnumerable無法使用它的原因有一些爭論),因此在使用它之前需要調用「ToList」。儘管它返回void,而不是另一個列表。但是爲IEnumerable編寫你自己的擴展方法並不重要。 – user1242967

+0

@ user1242967有沒有*辯論*爲什麼它不存在'IEnumerable'。對於IEnumerable是否是個好主意還存在爭議,但爲什麼它沒有明確規定,也沒有問題。 – Servy

+0

@Servy是的,對我來說不好的措辭。 – user1242967

回答

5

有一個在LINQ沒有Peek等效 - 即沒有執行一些動作返回源元件的方法。在List類中有一個ForEach方法,它對每個元素執行操作,但它不返回源元素,並且如前所述,它不是IEnumerable擴展名。

但是你可以很容易地編寫自己的擴展

public static IEnumerable<T> Peek<T>(this IEnumerable<T> source, Action<T> action) 
{ 
    if (source == null) throw new ArgumentNullException(nameof(source)); 
    if (action == null) throw new ArgumentNullException(nameof(action)); 

    return Iterator(); 

    IEnumerable<T> Iterator() // C# 7 Local Function 
    { 
     foreach(var item in source) 
     { 
      action(item); 
      yield return item; 
     } 
    } 
} 
+1

我認爲聲明一個本地函數只是爲了執行它,並返回結果是多餘的。您只需使用foreach塊就可以獲得相同的效果。 –

+1

@MattJohnson以及參數檢查如何與延遲執行一起工作? –

+0

延遲執行通過使用「yield return」來實現 - 而不是通過調用函數。您仍然可以按照當前寫入的順序執行延期執行,並且如果您內聯函數。 (注意你根本沒有返回函數,你只是在執行它。) –

1

編輯:這個答案已過時,編輯後的原始問題。最初的問題是措辭與peek -ing所有filter -ed值的意向,然後進行findFirst

List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); 
Optional<Integer> result = integerList.stream() 
             .filter(i -> i % 2 ==0== 0) 
             .peek(System.out::println) 
             .findFirst(); 

據我所知,沒有內置的LINQ解決方案要做到這一點,所以這裏的擴展方法:

public static IEnumerable<T> Peek<T>(this IEnumerable<T> source, Action<T> action) 
{ 
    using (var iterator = source.GetEnumerator()) 
    { 
     while (iterator.MoveNext()) 
     { 
      action(iterator.Current); 
     } 
    } 

    using (var iterator = source.GetEnumerator()) 
    { 
     while (iterator.MoveNext()) 
     { 
      yield return iterator.Current; 
     } 
    } 
} 

用法:

var integerList = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
int? result = integerList.Where(i => i % 2 == 0) 
         .Peek(i => Console.WriteLine(i)) 
         .FirstOrDefault(); 

Console.WriteLine(result); 

輸出:

2 
4 
6 
8 
10 
2 
4

您可以使用SelectStatement Lambda這一點。考慮:

var integerList = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
var result = integerList 
    .Where(i => i % 2 == 0) 

    // this select uses a statement lambda 
    .Select(i => 
    { 
     Console.WriteLine(i); 
     return i; 
    }) 

    .Whatever(...); 
相關問題