【问题标题】:How to filter only a element from a sequence (IEnumerable) in LINQ如何在 LINQ 中仅过滤序列(IEnumerable)中的元素
【发布时间】:2017-08-12 08:38:36
【问题描述】:

例如:{ 1,2,3,4,5,3,6}.Filter(i => i.Equals(3)) 将变为 {1,2,4,5,3,6}

我现在的方式:

array
.TakeWhile(i => !i.Equals(min))
.Concat(array.SkipWhile(i => !i.Equals(min)).Skip(1))

我希望有一些比这更优雅(更短)的方法

【问题讨论】:

  • 你有一个 Where 函数...
  • 在哪里过滤多个元素,我想要的只是一个元素。 {1,2,3,4,5,3,6}.Where(i =>! i.Equals(3)) => {1,2,4,5,6}。我想要什么:{1,2,3,4,5,3,6}.Filter(i => i.Equals(3)) => {1,2,4,5,3,6}.
  • 是不是更优雅int count = 0; { 1, 2, 3, 4, 5, 3, 6 }.Where(i => !i.Equals(3) || count++ > 0);
  • 修复它,请再次检查。
  • { 1,2,3,4,5,3,6,3}变成{ 1,2,4,5,3,6}吗?

标签: c# .net linq .net-core


【解决方案1】:

好吧,为了更清晰的阅读,我认为如果我将其作为答案而不是评论发布会更好。

var array = new List<int> { 1, 2, 3, 4, 5, 3, 6 };
int count = 0; 
array = array.Where(i => !i.Equals(3) || count++ > 0).ToList();

【讨论】:

    【解决方案2】:

    我不知道过滤器在哪里工作,但如果我只想从 IEnumerable 中删除一项,我会使用它。

    public static class LinqExtensions
        {
            public static IEnumerable<TSource> RemoveOne<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
            {
                var found = false;
                foreach (var item in source)
                {
                    if (!found && predicate(item))
                    {
                        found = true;
                    }
                    else
                    {
                        yield return item;
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案3】:

      只需为@George Alexandria 添加扩展和更通用的方法即可:

      public static class LinqExtentions
      {
          public static IEnumerable<T> RemoveNumberByCondition<T>(this IEnumerable<T> collection,
             Func<T, bool> predicate, 
             int numberToRemove = 1)
          {
              var count = 0;
              return collection.Where(x => predicate(x) || ++count > numberToRemove).ToArray();
          }
      }
      

      用法:

      var min = 3;
      var arr = new[] { 1, 2, 3, 4, 5, 3, 6 };
      var res = arr.RemoveNumberByCondition(x => !x.Equals(min));
      

      【讨论】:

      • 两全其美^^.
      • btw,你的方法反过来了,应该是这样的:arr.WithoutOne(x =&gt; x.Equals(min));
      • @Snoob fair enought.
      • 不,一般情况下它不起作用。试试var r1 = res.ToList(); var r2 = res.ToList();,你会发现r2 是错误的。如果您使用 iterator 方法实现(使用 foreachyield)而不是 LINQ,则无论您迭代多少次,结果都是正确的。
      • @Snoob 看看我的this question。答案已经足够了解里面到底发生了什么。
      【解决方案4】:
      public static class LinqExtensions
      {
          public static IEnumerable<TSource> SkipFirstWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
          {
              if (source == null) throw new ArgumentNullException(nameof(source));
              if (predicate == null) throw new ArgumentNullException(nameof(predicate));
              return SkipFirstWhereIterator(source, predicate);
          }
      
          private static IEnumerable<TSource> SkipFirstWhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
          {
              using (var e = source.GetEnumerator())
              {
                  while (true)
                  {
                      if (!e.MoveNext()) yield break;
                      if (predicate(e.Current)) break;
                      yield return e.Current;
                  }
                  while (e.MoveNext())
                      yield return e.Current;
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-05
        • 1970-01-01
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 2021-07-22
        相关资源
        最近更新 更多