【问题标题】:LINQ: How to Use RemoveAll without using For loop with ArrayLINQ:如何在不使用 For 循环的情况下使用 RemoveAll
【发布时间】:2011-02-22 11:41:03
【问题描述】:

我目前有一个日志对象,我想根据 LINQ 查询从中删除对象。如果程序中的版本总和大于 60,我想删除日志中的所有记录。目前我很有信心这会起作用,但它似乎很笨拙:

        for (int index = 0; index < 4; index++)
        {
          Log.RemoveAll(log =>
                    (log.Program[index].Version[0].Value +
                     log.Program[index].Version[1].Value +
                     log.Program[index].Version[2].Value ) > 60);
        }

程序是一个包含 4 个值的数组,而版本有一个包含 3 个值的数组。有没有更简单的方法可以在不使用 for 循环的情况下在 LINQ 中执行 RemoveAll?

提前感谢您的帮助!


编辑: 不幸的是,Program 和 Version 所基于的变量类型(这是我正在使用的框架的一个约束)限制了我们,以至于我无法访问“Any”成员。但是,如果您有 lists,我通过创建一些示例代码确认了 tzaman 的解决方案有效。我仅限于类似数组的变量(请参阅注释掉的区域)

// I'm restricted to Arrays, but if I had lists, this would work. 
  internal class MyLogCollection
  {
    List<MyLog> MyListOfZones = new List<MyLog>();

    public void TestRemove()
    {
      // Original Implementation
      for (int i = 0; i < 4; i++)
      {
        MyListOfZones.RemoveAll(log => (log.MyZoneArray[0].MyVersionArray[0].Value +
                                        log.MyZoneArray[0].MyVersionArray[1].Value +
                                        log.MyZoneArray[0].MyVersionArray[2].Value) > 60);
        //"Any" method is not available off of intellisense scope on MyZoneArray 
      }

      // Better Implementation (thanks tzaman!)
      MyListOfZones.RemoveAll(log => (log.MyZoneArray.Any(prog =>
                                                          prog.MyVersionArray.Sum(ver => ver.Value) > 60)));
    }
  }
  internal class MyLog
  {
    //public MyZone[] MyZoneArray = new MyZone[4];

    public List<MyZone> MyZoneArray = new List<MyZone>(4);

  }
  internal class MyZone
  {
    //public MyVersion[] MyVersionArray = new MyVersion[3];
    public List<MyVersion> MyVersionArray = new List<MyVersion>(3);
  }
  internal class MyVersion
  {
    public byte Value { get; set;}

  }

谢谢你!

【问题讨论】:

  • 只是Any 不起作用,或者没有一个LINQ 运算符起作用?它是常规的System.Array 类型,还是带有重载索引运算符的自定义类型?如果是后者,您将无法使用 LINQ afaik,除非您能以某种方式从中获得 IEnumerable。你可以很容易地定义一个扩展方法来为你做这件事(使用for循环和yield return)......如果你需要一个例子,我可以更新我的答案。
  • @tzaman - 抱歉回复晚了 - 没有一个操作员工作。它是一个“类似数组”的对象,我 90% 确信它不是系统数组类型。我知道它现在不是 IEnumerable :-/。如果您确实知道如何创建 IEnumerable,我将不胜感激 :-)

标签: c# linq lambda removeall


【解决方案1】:

我认为应该这样做:

Log.RemoveAll(log => 
              log.Program.Any(prog => 
                              prog.Version.Sum(ver => ver.Value) > 60));


编辑: 好的,下面介绍如何添加扩展方法以从可索引的“类数组”对象中获取 IEnumerables,以便您可以在它们上使用 LINQ:

static class MyExtensions
{
    public static IEnumerable<MyZone> Enumerate(this MyZoneArray zone)
    {
        for (int i = 0; i < zone.Length; i++)
            yield return zone[i];
    }

    public static IEnumerable<MyVersion> Enumerate(this MyVersionArray version)
    {
        for (int i = 0; i < version.Length; i++)
            yield return version[i]
    }
}

我假设MyZoneArrayMyVersionArray 类型有一个Length 字段,但如果没有,您可以在那边输入43。有了这些,您现在可以在集合对象上调用 Enumerate() 函数以获取集合的 IEnumerable 版本,并附加所有相关的 LINQy 优点:log.MyZoneArray.Enumerate().Any( ... )

【讨论】:

  • 啊!对我来说太快了。很好的答案:)
  • 嗯。由于某种原因,我无法从程序变量中使用“任何”方法。您的解决方案可能工作正常,但我试图用另一组阵列对其进行测试,但它不能正常工作。我认为如果我使用列表(或者在我的实现中灵活地使用列表)而不是数组,它会正常工作。
  • 不过,这很奇怪; Any 是一种标准的 LINQ 方法,它应该可用于任何数组对象。它适用于Version吗?
猜你喜欢
  • 2017-03-30
  • 1970-01-01
  • 2023-02-05
  • 2021-05-29
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
相关资源
最近更新 更多