2017-07-07 73 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(...); 
相关问题