I need to access the current and previous element in an IQueryable object. If I had an int array, I would do the following:
我需要访问IQueryable对象中的当前和前一个元素。如果我有一个int数组,我会做以下事情:
var array = new int[]{0,1,2,3,4};
for(var i = 1; i<array.Length ; i++)
{
method1(array[i-1], array[i]);
}
I don't know to do the same with IQueryable, since it does not implement IList.
我不知道对IQueryable做同样的事情,因为它没有实现IList。
5 个解决方案
#1
Using extension methods makes this fairly easy.
使用扩展方法使这相当容易。
public static class IEnumerableExtensions
{
public static IEnumerable<ValueWithPrevious<T>> WithPrevious<T>(this IEnumerable<T> @this)
{
using (var e = @this.GetEnumerator())
{
if (!e.MoveNext())
yield break;
var previous = e.Current;
while (e.MoveNext())
{
yield return new ValueWithPrevious<T>(e.Current, previous);
previous = e.Current;
}
}
}
}
public struct ValueWithPrevious<T>
{
public readonly T Value, Previous;
public ValueWithPrevious(T value, T previous)
{
Value = value;
Previous = previous;
}
}
Usage:
var array = new int[] { 1, 2, 3, 4, 5 };
foreach (var value in array.WithPrevious())
{
Console.WriteLine("{0}, {1}", value.Previous, value.Value);
// Results: 1, 2
// 2, 3
// 3, 4
// 4, 5
}
#2
You can turn an IQueryable<> into a List<> using ToList<>().
您可以使用ToList <>()将IQueryable <>转换为List <>。
#3
EDIT
Misread the question a bit. This code will give you consequetive elements
误读了一下这个问题。此代码将为您提供相关元素
public static IEnumerable<Pair<T,T>> GroupIntoConsequetive(this IEnumerable<T> enumerable) {
using ( var e = enumerable.GetEnumerator() ) {
if ( !e.MoveNext() ) {
yield break;
}
var last = e.Current;
while ( e.MoveNext() ) {
yield return new Pair<T,T>(last, e.Current);
last = e.Current;
}
}
}
I'm not sure there is default way but writing an extension method to do so shouldn't be to difficult. I'm assuming there is a simple Pair implementation
我不确定是否有默认方式,但编写扩展方法这样做应该不会很困难。我假设有一个简单的Pair实现
public static IEnumerable<Pair<T,T>> Window(this IEnumerable<T> enumerable) {
using ( var e = enumerable.GetEnumerator() ) {
while ( e.MoveNext() ) {
var first = e.Current;
if ( !e.MoveNext() ) {
throw new InvalidOperationException("Need even number");
}
var second = e.Current;
yield return new Pair<T,T>(first,second);
}
}
}
With the window you could then get the behavior you desire with the following
通过窗口,您可以通过以下方式获得所需的行为
var col = GetQueryableItem();
col.Window().Select(pair => method1(pair.First, pair.Second));
Quick and dirty Pair implementation
快速而脏的Pair实现
public struct Pair<T1,T2> {
public readonly T1 First;
public readonly T2 Second;
public Pair(T1 first, T2 second) {
First = first;
Second = second;
}
}
#4
#5
IQueryable is IEnumerable. So you can do something like:
IQueryable是IEnumerable。所以你可以这样做:
var a = new [] {1, 2, 3, 4}.AsQueryable();
if (a.Count() < 2) {
return;
}
var prev = a.First();
var isFirst = true;
foreach (var i in a) {
if (isFirst) {
isFirst = false;
continue;
}
method1(prev, i);
prev = i;
}
Or simply convert IQueryable into IList:
或者只是将IQueryable转换为IList:
var list = a.ToList();
#1
Using extension methods makes this fairly easy.
使用扩展方法使这相当容易。
public static class IEnumerableExtensions
{
public static IEnumerable<ValueWithPrevious<T>> WithPrevious<T>(this IEnumerable<T> @this)
{
using (var e = @this.GetEnumerator())
{
if (!e.MoveNext())
yield break;
var previous = e.Current;
while (e.MoveNext())
{
yield return new ValueWithPrevious<T>(e.Current, previous);
previous = e.Current;
}
}
}
}
public struct ValueWithPrevious<T>
{
public readonly T Value, Previous;
public ValueWithPrevious(T value, T previous)
{
Value = value;
Previous = previous;
}
}
Usage:
var array = new int[] { 1, 2, 3, 4, 5 };
foreach (var value in array.WithPrevious())
{
Console.WriteLine("{0}, {1}", value.Previous, value.Value);
// Results: 1, 2
// 2, 3
// 3, 4
// 4, 5
}
#2
You can turn an IQueryable<> into a List<> using ToList<>().
您可以使用ToList <>()将IQueryable <>转换为List <>。
#3
EDIT
Misread the question a bit. This code will give you consequetive elements
误读了一下这个问题。此代码将为您提供相关元素
public static IEnumerable<Pair<T,T>> GroupIntoConsequetive(this IEnumerable<T> enumerable) {
using ( var e = enumerable.GetEnumerator() ) {
if ( !e.MoveNext() ) {
yield break;
}
var last = e.Current;
while ( e.MoveNext() ) {
yield return new Pair<T,T>(last, e.Current);
last = e.Current;
}
}
}
I'm not sure there is default way but writing an extension method to do so shouldn't be to difficult. I'm assuming there is a simple Pair implementation
我不确定是否有默认方式,但编写扩展方法这样做应该不会很困难。我假设有一个简单的Pair实现
public static IEnumerable<Pair<T,T>> Window(this IEnumerable<T> enumerable) {
using ( var e = enumerable.GetEnumerator() ) {
while ( e.MoveNext() ) {
var first = e.Current;
if ( !e.MoveNext() ) {
throw new InvalidOperationException("Need even number");
}
var second = e.Current;
yield return new Pair<T,T>(first,second);
}
}
}
With the window you could then get the behavior you desire with the following
通过窗口,您可以通过以下方式获得所需的行为
var col = GetQueryableItem();
col.Window().Select(pair => method1(pair.First, pair.Second));
Quick and dirty Pair implementation
快速而脏的Pair实现
public struct Pair<T1,T2> {
public readonly T1 First;
public readonly T2 Second;
public Pair(T1 first, T2 second) {
First = first;
Second = second;
}
}
#4
But it provides extension methods to create an array or a list from your IQueryable<T>
instance, see ToArray() and ToList(). You can then go and do the same as you would with the array in your example.
但它提供了从IQueryable
#5
IQueryable is IEnumerable. So you can do something like:
IQueryable是IEnumerable。所以你可以这样做:
var a = new [] {1, 2, 3, 4}.AsQueryable();
if (a.Count() < 2) {
return;
}
var prev = a.First();
var isFirst = true;
foreach (var i in a) {
if (isFirst) {
isFirst = false;
continue;
}
method1(prev, i);
prev = i;
}
Or simply convert IQueryable into IList:
或者只是将IQueryable转换为IList:
var list = a.ToList();