【问题标题】:Filtering List from a List从列表中过滤列表
【发布时间】:2017-08-26 05:43:20
【问题描述】:

底线是我想要一个 linq 语句,它返回与下面的代码相同的列表。

我觉得这是可能的,我觉得在我放弃之前我已经非常接近了,只是用更多的代码行来说明我想要的。

虽然我会喜欢并感谢任何能够展示我希望为未来实现的目标并取代我所拥有的东西的人。

public ObservableCollection<VarItem> IndexChannels 
{
    get
    {
        ObservableCollection<VarItem> filtered = new ObservableCollection<VarItem>();

        filtered.Add(indexChannels.First());//add Disabled no matter what

        //add the cur channels selected index if it isn't already disabled
        if (!filtered.Contains(indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel)))
        {
           filtered.Add(indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel));
        }

        foreach (PdioChannelModel ch in channels)
        {
           //if the channels mode isn't q-decode or quad index add its Number as an index
           if (ch.Mode.Value != "Q-Decode" && ch.Mode.Value != "Quad Index") 
           {
              filtered.Add(indexChannels.FirstOrDefault(i => i.ID == ch.Number));
           }
        }
        return filtered;
    }
}

VarItem的基本结构

公共类 VarItem { 公共 int ID { 获取;私人套装; } 公共字符串值 { 获取;私人套装; } 公共字典元数据 { 获取;私人套装; }

  public VarItem(int id, string value)
  {
     this.ID = id;
     this.Value = value;
     MetaData = new Dictionary<string, string>();
  }

示例主列表包含 VarItems:

-1,“禁用”

1,“频道 1”

2,“频道 2”

3,“频道 3”

过滤列表应始终包含VarItem(-1, Disabled)。它还应该包含VarItem,其中ID匹配CurChannel.IndexChannel,最后它应该包含任何VarItems,其中ID匹配任何PdioChannelModel.Number,其中PdioChannelModel.Mode.Value != "Q-Decode" or "Quad Index"

如果我错过了任何需要的细节,请告诉我。如果我让您感到困惑并写了很多或需要澄清,请告诉我。

【问题讨论】:

  • 您是否尝试用一个 linq 或 jsut foreach 位替换所有代码,因为虽然您可以将其写为一个命令,但实际上它实际上是在做三种不同的事情(默认,当前, 过滤) 可能意味着将这些内容分开更易读。 foreach 可能很容易更改为 filtered.AddRange 和 Where 后跟 Select 如果这就是您想要的,但我再次倾向于“如果它没有损坏,请不要修复它”。当然,作为下一次的学习练习,它仍然有用...... :)
  • 一些问题。 channels 来自哪里?和indexChannels是同一类型吗? IndexChannels(大写 I)是错字吗?是否保证indexChannels.First() 始终是“禁用”项?我认为这可以通过过滤和排序来实现。

标签: c# linq filter


【解决方案1】:

一种方法是生成要添加的项目列表并将其传递给构造函数。

我们确定我们想要 indexChannels 中的第一项,以及当前频道选择的索引(如果它在那里),所以这部分非常简单 - 只需一个 new List&lt;VarItem&gt;

接下来,您要添加 ID 与模式不是 Q-Decode 或 Quad Index 的通道编号匹配的所有索引通道。因此,为此我将使用Union 将其与第一个列表一起加入。

最后,由于FirstOrDefault 返回default(VarItem) 作为默认值,我们可以在最后删除它们,我们也可以在其中抛出Distinct 以确保我们没有重复:

get
{
    return new ObservableCollection<VarItem>((
        new List<VarItem>
        {
            indexChannels.First(),
            indexChannels.FirstOrDefault(i => i == CurChannel.IndexChannel)
        })
        .Union(channels
            .Where(ch => ch.Mode.Value != "Q-Decode" &&
                         ch.Mode.Value != "Quad Index")
            .Select(ch => indexChannels.FirstOrDefault(i => i.ID == ch.Number)))
        .Where(varItem => varItem != default(VarItem))
        .Distinct());
}

为了记录,我永远不会在生产代码中这样做。该语句中的任何失败都将是调试的巨大痛苦。一般每行做一个语句,在一行失败时,其他人更容易阅读,也更容易调试。

【讨论】:

    【解决方案2】:

    您是否关心将null 值添加到您的ObservableCollection?如果您想排除null 值,那么FirstOrDefault 不是在foreach 中使用的正确方法。另一方面,如果您确定每个频道Number 属性将在indexChannels 中存在至少一次,那么只需使用First。这样,如果您的假设是错误的(并且Number 与任何ID 都不匹配),那么First 将抛出一个异常,这可能是您想要的,而不是稍后的NullReferenceException,这将更难调试.此外,如果您确定每个通道Number 属性在indexChannels 中只存在一次,则使用Single,因此当违反第二个假设时会出现异常。同样,这比以后的一些意外行为更容易调试。

    这是一个示例解决方案:

    return new ObservableCollection<VarItem>(
        indexChannels
        .Take(1)
        .Union(indexChannels.Where(i => i == CurChannel.IndexChannel).Take(1))
        .Union(channels
            .Where(c => c.Mode.Value != "Q-Decode" &&
                        c.Mode.Value != "Quad Index")
            // The following line could be turned into
            // .Select(c => indexChannels.First(i => i.ID == c.Number))
            // OR
            // .Select(c => indexChannels.Single(i => i.ID == c.Number))
            // OR 
            // .SelectMany(c => indexChannels.Where(i => i.ID == c.Number))
            // depending on how many channels in indexChannels 
            // are expected to match each Number property.
            .Select(c => indexChannels.FirstOrDefault(i => i.ID == c.Number))
    );
    

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 2021-08-18
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-15
      • 2013-09-29
      相关资源
      最近更新 更多