通过C#中集合的子集枚举?
在C#中,是否有一种只枚举集合子集的好方法?也就是说,我有一个大量对象的集合(比如说,1000个),但我只想枚举250-340个元素。有没有一种好方法可以在不使用其他集合的情况下获取集合子集的枚举数 编辑:应该提到这是在使用.NET Framework 2.0。请尝试以下操作通过C#中集合的子集枚举?,c#,collections,.net-2.0,enumeration,subset,C#,Collections,.net 2.0,Enumeration,Subset,在C#中,是否有一种只枚举集合子集的好方法?也就是说,我有一个大量对象的集合(比如说,1000个),但我只想枚举250-340个元素。有没有一种好方法可以在不使用其他集合的情况下获取集合子集的枚举数 编辑:应该提到这是在使用.NET Framework 2.0。请尝试以下操作 var col = GetTheCollection(); var subset = col.Skip(250).Take(90); 或者更一般地说 public static IEnumerable<T>
var col = GetTheCollection();
var subset = col.Skip(250).Take(90);
或者更一般地说
public static IEnumerable<T> GetRange(this IEnumerable<T> source, int start, int end) {
// Error checking removed
return source.Skip(start).Take(end - start);
}
公共静态IEnumerable GetRange(此IEnumerable源,int开始,int结束){
//已删除错误检查
返回源。跳过(开始)。获取(结束-开始);
}
编辑2.0解决方案
public static IEnumerable<T> GetRange<T>(IEnumerable<T> source, int start, int end ) {
using ( var e = source.GetEnumerator() ){
var i = 0;
while ( i < start && e.MoveNext() ) { i++; }
while ( i < end && e.MoveNext() ) {
yield return e.Current;
i++;
}
}
}
IEnumerable<Foo> col = GetTheCollection();
IEnumerable<Foo> range = GetRange(col, 250, 340);
公共静态IEnumerable GetRange(IEnumerable源、int开始、int结束){
使用(var e=source.GetEnumerator()){
var i=0;
而(i
您也许可以用Linq做点什么。我这样做的方法是将对象放入一个数组中,然后我可以根据数组id选择要处理的项目。如果您发现需要对列表和集合进行大量的切片和切分,那么可能值得沿着学习曲线前进。我喜欢保持简单(如果您不一定需要枚举器):
for(inti=249;i
改编Jared针对.Net 2.0的原始代码:
IEnumerable<T> GetRange(IEnumerable<T> source, int start, int end)
{
int i = 0;
foreach (T item in source)
{
i++;
if (i>end) yield break;
if (i>start) yield return item;
}
}
再次修改Jarad的代码,这个扩展方法将得到一个子集,它是由项定义的,而不是由索引定义的
//! Get subset of collection between \a start and \a end, inclusive
//! Usage
//! \code
//! using ExtensionMethods;
//! ...
//! var subset = MyList.GetRange(firstItem, secondItem);
//! \endcode
class ExtensionMethods
{
public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, T start, T end)
{
#if DEBUG
if (source.ToList().IndexOf(start) > source.ToList().IndexOf(end))
throw new ArgumentException("Start must be earlier in the enumerable than end, or both must be the same");
#endif
yield return start;
if (start.Equals(end))
yield break; //start == end, so we are finished here
using (var e = source.GetEnumerator())
{
while (e.MoveNext() && !e.Current.Equals(start)); //skip until start
while (!e.Current.Equals(end) && e.MoveNext()) //return items between start and end
yield return e.Current;
}
}
}
//!获取\a开始和\a结束之间的集合子集,包括
//!用法
//!\code
//!使用ExtensionMethods;
//! ...
//!var subset=MyList.GetRange(第一项,第二项);
//!\endcode
类扩展方法
{
公共静态IEnumerable GetRange(此IEnumerable源,T开始,T结束)
{
#如果调试
if(source.ToList().IndexOf(start)>source.ToList().IndexOf(end))
抛出新ArgumentException(“开始必须早于结束,或者两者必须相同”);
#恩迪夫
收益率-收益率开始;
如果(开始等于(结束))
屈服中断;//开始==结束,所以我们到此结束
使用(var e=source.GetEnumerator())
{
while(e.MoveNext()&&&!e.Current.Equals(start));//跳过直到开始
而(!e.Current.Equals(end)&&e.MoveNext())//在开始和结束之间返回项
收益率,收益率,电流;
}
}
}
我喜欢这种扩展方法。很抱歉,这是在使用.NET 2.0;skip不可用。如果是在.NET 3.5中,这将是金色的。@McWafflestix添加了一个2.0解决方案,它在2.0中实现了这一点;没有在3.5中那么简洁,但它可以工作。@McWafflestix,是的。关于LINQ最好的一点是brevityThis比公认的解决方案简单得多答案…在我看来,如果我们要得到一个非常大的列表末尾的项目,这是有好处的。被接受的答案将不必要地从一开始就横穿…考虑到所有这些,我很困惑为什么这个答案的上升票如此之少。我是否遗漏了这个答案的一些技术性内容?或者这只是一个例子如果您在另一个答案被接受后发布此答案,那么实际上没有多少人查看它。@AmithGeorge大多数其他答案都适用于所有实现IEnumerable的集合。此答案仅适用于希望实现IList或其他数字索引器/下标的人。我希望这能澄清问题。
foreach (T item in GetRange(MyCollection, 250, 340))
{
// do something
}
//! Get subset of collection between \a start and \a end, inclusive
//! Usage
//! \code
//! using ExtensionMethods;
//! ...
//! var subset = MyList.GetRange(firstItem, secondItem);
//! \endcode
class ExtensionMethods
{
public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, T start, T end)
{
#if DEBUG
if (source.ToList().IndexOf(start) > source.ToList().IndexOf(end))
throw new ArgumentException("Start must be earlier in the enumerable than end, or both must be the same");
#endif
yield return start;
if (start.Equals(end))
yield break; //start == end, so we are finished here
using (var e = source.GetEnumerator())
{
while (e.MoveNext() && !e.Current.Equals(start)); //skip until start
while (!e.Current.Equals(end) && e.MoveNext()) //return items between start and end
yield return e.Current;
}
}
}