Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 筛选比较同一集合的两个元素的lambda表达式_C#_Linq_Lambda_Comparison - Fatal编程技术网

C# 筛选比较同一集合的两个元素的lambda表达式

C# 筛选比较同一集合的两个元素的lambda表达式,c#,linq,lambda,comparison,C#,Linq,Lambda,Comparison,我想知道是否可以为Linq扩展(或自定义扩展)编写一个表达式,以使用比较集合的两个元素的lambda表达式过滤集合 换句话说,如果我有一个列表和一些值,var v=DateTime.Today,那么我想知道是否可以编写一个方法来返回集合中小于或等于值current=v的第一个元素 请注意,以上只是一个示例,可能是也可能不是最终实现 如果使用.First()方法接受Func,并且两个DateTime参数是序列的连续元素,则以下是有效的解决方案: dateCollection.First((cur

我想知道是否可以为Linq扩展(或自定义扩展)编写一个表达式,以使用比较集合的两个元素的lambda表达式过滤集合


换句话说,如果我有一个
列表
和一些值,
var v=DateTime.Today
,那么我想知道是否可以编写一个方法来返回集合中小于或等于值
current=v
的第一个元素

请注意,以上只是一个示例,可能是也可能不是最终实现


如果使用
.First()
方法接受
Func
,并且两个
DateTime
参数是序列的连续元素,则以下是有效的解决方案:

dateCollection.First((current, next) => current <= v && next >= v);
我相信这也需要两个或更多的lambda表达式作为参数。还有一件事可能提供一个很好的解决方案,那就是能够选择序列中所有可能的、连续的元素对,并在此基础上调用
.First()
方法

例如:

//value 
var v = 5;

//if my collection is the following
List<int> stuff = { a, b, c, d };

//select into consecutive pairs, giving: 
var pairs = ... // { { a, b }, { b, c }, { c, d } };

//then run comparison
pairs.First(p => p[0] <= v && p[1] >= v).Select(p => p[0]);
//值
var v=5;
//如果我的收藏如下
列表内容={a,b,c,d};
//选择连续对,给出:
变量对=…//{a,b},{b,c},{c,d};
//然后运行比较
首先(p=>p[0]=v)。选择(p=>p[0]);


谢谢,祝您编码愉快!:)

严格按照描述,您可以将linq和list索引结合起来,找到与您的准则匹配的第一个索引,并返回其元素:

DateTime d= DateTime.Today;
var res = dateCollection[Enumerable.Range(0, dateCollection.Count - 1).First(i => dateCollection[i] <= d && dateCollection[i + 1] >= d)];
DateTime d=DateTime.Today;
var res=dateCollection[Enumerable.Range(0,dateCollection.Count-1).First(i=>dateCollection[i]=d)];

我的主要问题是不确定您想返回什么,但以您的示例为例,将其放入LINQ语句中,如下所示:

DateTime? Firstmatch = dateCollection.DefaultIfEmpty(null).FirstOrDefault(a => a <= d && ((dateCollection.IndexOf(a) + 1) < (dateCollection.Count) && dateCollection[dateCollection.IndexOf(a) + 1] >= d));
DateTime?Firstmatch=dateCollection.DefaultIfEmpty(null).FirstOrDefault(a=>a=d));

我们可以创建一个
成对的
方法,它可以将一个值序列映射成一个表示每个值及其前面的值的成对序列

public static IEnumerable<Tuple<T, T>> Pairwise<T>(this IEnumerable<T> source)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        T prev = iterator.Current;

        while (iterator.MoveNext())
        {
            yield return Tuple.Create(prev, iterator.Current);
            prev = iterator.Current;
        }
    }
}
公共静态IEnumerable成对(此IEnumerable源代码)
{
使用(var iterator=source.GetEnumerator())
{
如果(!iterator.MoveNext())
屈服断裂;
T prev=当前迭代器;
while(iterator.MoveNext())
{
返回Tuple.Create(prev,iterator.Current);
prev=迭代器。当前;
}
}
}
现在我们可以写出:

var item = data.Pairwise()
    .First(pair => pair.Item1 <= v && pair.Item2 >= v)
    .Item1;
var item=data.Pairwise()
.First(pair=>pair.Item1=v)
.项目1;
如果这是您将要使用的内容,那么创建一个新的自定义类型来替换
Tuple
,这样您就可以拥有
当前
下一个
属性,而不是
Item1
Item2
列表=新列表();
    List<int> list = new List<int>();
    list.Add(3);
    list.Add(2);
    list.Add(8);
    list.Add(1);
    list.Add(4);

    var element = list
         .Where((elem, idx) => idx < list.Count-1 && elem<=list[idx+1])
         .FirstOrDefault();

    Console.WriteLine(element);
增加(3); 增加(2); 增加(8); 增加第(1)款; 增加(4); var元素=列表
其中((elem,idx)=>idx
var first = items
  .Select((current, index) => index > 0 ? new { Prev = items.ElementAt(index-1), Current = current } : null)
  .First(pair => pair != null && pair.Prev <= v && pair.Current >= v)
  .Prev;      
var first=项目
.Select((当前,索引)=>index>0?新建{Prev=items.ElementAt(索引-1),当前=current}:null)
.First(pair=>pair!=null&&pair.Prev=v)
.Prev;


我的主要问题是不确定要返回什么?单个DateTime对象还是多个?“创建一个方法,该方法将返回集合中小于或等于该值的第一个元素”…这必须是单个对象中的多个lambdamethod@Ric “集合的下一个元素大于或等于该值“尽管如此,仍然返回一个对象。我喜欢它,并且正在投票,因为它是一个完全有效的解决方案。但是,我希望可能有一个解决方案只涉及一个使用一个或多个lambda表达式的方法。这实际上比我的好,因为范围选项…:)我相信
范围
调用实际上是不必要的。除非我弄错了,否则您可以使用内置索引器。如果没有,则执行
。其中((元素,i)=>…)。First()
将是相同的。尽管如此,这仍然是一个很好的解决方案,这也是我投票的原因;)这假设集合是可索引的,如果它是任意的
IEnumerable
,它可能不是。@Servy是的,但原始示例确实说*List*与@Me.Name的解决方案非常相似,但我喜欢取消对
.Range()
极好的解决方案@Servy的调用!这不仅完全符合我所寻找的,而且也说明了不可复制的收藏@ZacharyKniebel你的意思是可转位的,不是可转位的,但是是的。哈哈哈,是的,我的意思是可转位的。Iterable会很傻:p这是我在对另一个答案的评论中提到的
.Where.First
解决方案。非常干净,有效!谢谢你,艾莉!凯西-谢谢你的回答。然而,@Servy的答案为那些可能不可索引的集合提供了支持,这就是他添加扩展方法的原因。不过,您的解决方案不错;)+1“不可转位”是什么意思?是否所有IEnumerable都不支持我使用的.Select方法,而不考虑T?这是一个O(n^2)操作。我的是一个O(n)操作
ElementAt
IEnumerable
上的一个O(n)操作,因此在循环中调用它以获取前一项是一个非常糟糕的主意。您最好将查询具体化为一个列表,然后使用依赖于数据源的具有索引器的其他解决方案之一,而不是使用此解决方案。好的,我明白您的意思。也就是说,我不知道你是否可以说它是一个O(n^2)操作——这是否真的取决于底层可枚举函数是否实现了IL
var first = items
  .Select((current, index) => index > 0 ? new { Prev = items.ElementAt(index-1), Current = current } : null)
  .First(pair => pair != null && pair.Prev <= v && pair.Current >= v)
  .Prev;