我需要一个 double[] 通过跨步 y 分成 x 元素组,返回一个列表。非常基本...一个循环和/或一些 linq 以及所有设置。然而,我并没有在扩展方法上花费太多时间,这看起来是一些练习的不错选择。 朴素版本返回我在当前应用程序中寻找的内容...
(A)
public static IList<T[]> Split<T>(this IEnumerable<T> source, int every, int take)
{
/*... throw E if X is insane ...*/
var result = source
.Where ((t, i) => i % every == 0)
.Select((t, i) => source.Skip(i * every).Take(take).ToArray())
.ToList();
return result;
}
...返回类型是通用的...取决于您对通用的定义 。
我认为...
(B)
public static IEnumerable<IEnumerable<T>> Split<T>
(this IEnumerable<T> source,int every, int take){/*...*/}
...是一个更好的解决方案...也许。
问题:
- (B)是首选吗?...为什么?
- 您如何将 (B) 转换为
IList
?
- 重构有什么好处吗? 可能
两种可能被链接起来的方法或类似的方法。
- 这种方法合理吗?...或者我有吗?
错过了一些基本的东西。
评论、意见和严厉的语言总是受到赞赏。
使用环境:C# .Net 4.0
I needed a double[] split into groups of x elements by stride y returning a List. Pretty basic...a loop and/or some linq and your all set. However, I have not been spending much time on extension methods and this looked like a good candidate for some practice. The naive version returns what I am looking for in my current application....
(A)
public static IList<T[]> Split<T>(this IEnumerable<T> source, int every, int take)
{
/*... throw E if X is insane ...*/
var result = source
.Where ((t, i) => i % every == 0)
.Select((t, i) => source.Skip(i * every).Take(take).ToArray())
.ToList();
return result;
}
...the return type is sort of generic...depending on your definition of generic.
I would think...
(B)
public static IEnumerable<IEnumerable<T>> Split<T>
(this IEnumerable<T> source,int every, int take){/*...*/}
...is a better solution...maybe.
Question(s):
- Is (B) preferred ?...Why ?
- How would you cast (B) as
IList <T[]>
?
- Any benefit in refactoring ? possibly
two methods that might be chained or the like.
- Is the approach sound ?...or have I
missed something basic.
Comments, opinions and harsh language are always appreciated.
Usage Context: C# .Net 4.0
发布评论
评论(3)
B 可能是更好的选择。实际上,主要的变化是代码的使用者可以选择在方法末尾使用 ToList() 将其设置为列表,而不是被迫处理列表(实际上是 IList,无法迭代) 。
这在方法链接和一般使用方面有很多优点。 ToList() 是可枚举的很容易,但很难采用其他方法。因此,您可以在列表上调用 Select().Split().OrderBy() 并在 foreach 语句中使用结果,而不必让 Linq 立即迭代整个过程。
重构为
yield return
单个值可能会给你带来性能奖励,但由于你基本上只是返回 Select 给你的迭代器(它一次会产生一个项目),我不这样做认为你自己通过它屈服会得到很多好处。B is probably the better option. Really the major change is that the consumer of the code has the option to make it a list using ToList() on the end of your method, instead of being forced to deal with a List (an IList, actually, which cannot be iterated).
This has a LOT of advantages in method chaining and general use. It's easy to ToList() an enumerable, but hard to go the other way. So, you can call Select().Split().OrderBy() on a list and use the results in a foreach statement without having to have Linq iterate through the whole thing at once.
Refactoring to
yield return
single values MIGHT get you a performance bonus, but since you're basically just returning the iterator that the Select gave you (which will yield one item at a time itself) I don't think you'll get much benefit in yielding through it yourself.我更喜欢 (B),因为它看起来更灵活。将 (B) 方法的输出转换为
IList
的一种方法与链接.Select(x => x.ToArray()) 一样简单。 ToList()
到它,例如,I would prefer (B) as it looks more flexible. One way of casting the output of the (B) method to an
IList<T[]>
is as simple as chaining.Select(x => x.ToArray()).ToList()
to it, e.g.,在 .Net 4 中,您只需将返回类型更改为
IEnumerable>
即可。在 .Net 4 之前,您必须首先通过在
上调用
。.Cast>()
将内部列表转换为IEnumerable
返回之前的结果In .Net 4, you can just change the return type to
IEnumerable<IEnumerable<T>>
and it will work.Before .Net 4, you would have to cast the internal lists to
IEnumerable
first, by just calling.Cast<IEnumerable<T>>()
on yourresult
before returning.