扩展 IEnumerable 的 Select 以在选择器中包含源
Extension of IEnumerable's Select to include the source in the selector
IEnumerable 的重载之一是:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector);
我希望在选择器中包含来源。我知道这听起来有悖常理,因为您首先向 Select 提供了来源,但 JavaScript 有类似的东西。我想在像这里这样的快速情况下使用它:
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (name == source.First())
return $"{name} (Todays Winner)";
return name;
});
上面会出错,因为Select的selector参数没有return3个值。只是当前对象和索引。我希望它包含来源。
我不想先单独创建列表,然后再对其执行 .first。
这是我对扩展程序进行了多少;我不确定如何实现它。
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult, IEnumerable<TSource>> selector)
{
//not sure what to put in here, must be missing something simple ;(
}
更新
以上情况只是虚构的例子。我的实际情况需要使用 .Last()
而不是 .First()
因此索引不会有用,因为我们不知道最后一个索引是什么,而不是第一个为零。因此我需要传回源代码。
应该这样做:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
using (var enumerator = source.GetEnumerator()) {
for (var i = 0 ; enumerator.MoveNext() ; i++) {
yield return selector(enumerator.Current, i, source);
}
}
}
请注意,您为 selector
参数编写了错误的类型。应该是Func<TSource, int, IEnumerable<TSource>, TResult>
,不是Func<TSource, int, TResult, IEnumerable<TSource>>
.
如果你只想检查一个元素是否是第一个,为什么不检查 index == 0
?
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (index == 0)
return $"{name} (Todays Winner)";
return name;
});
这应该有效:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
int index = 0;
foreach(var item in source)
{
yield return selector(item, index, source);
index++;
}
}
IEnumerable 的重载之一是:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector);
我希望在选择器中包含来源。我知道这听起来有悖常理,因为您首先向 Select 提供了来源,但 JavaScript 有类似的东西。我想在像这里这样的快速情况下使用它:
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (name == source.First())
return $"{name} (Todays Winner)";
return name;
});
上面会出错,因为Select的selector参数没有return3个值。只是当前对象和索引。我希望它包含来源。
我不想先单独创建列表,然后再对其执行 .first。
这是我对扩展程序进行了多少;我不确定如何实现它。
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult, IEnumerable<TSource>> selector)
{
//not sure what to put in here, must be missing something simple ;(
}
更新
以上情况只是虚构的例子。我的实际情况需要使用 .Last()
而不是 .First()
因此索引不会有用,因为我们不知道最后一个索引是什么,而不是第一个为零。因此我需要传回源代码。
应该这样做:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
using (var enumerator = source.GetEnumerator()) {
for (var i = 0 ; enumerator.MoveNext() ; i++) {
yield return selector(enumerator.Current, i, source);
}
}
}
请注意,您为 selector
参数编写了错误的类型。应该是Func<TSource, int, IEnumerable<TSource>, TResult>
,不是Func<TSource, int, TResult, IEnumerable<TSource>>
.
如果你只想检查一个元素是否是第一个,为什么不检查 index == 0
?
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (index == 0)
return $"{name} (Todays Winner)";
return name;
});
这应该有效:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
int index = 0;
foreach(var item in source)
{
yield return selector(item, index, source);
index++;
}
}