【问题标题】:How to do a Linq on a comma separated string如何在逗号分隔的字符串上执行 Linq
【发布时间】:2017-03-15 07:35:12
【问题描述】:

我还有一个与此相关的问题:Filter an IEnumerable in Linq with an array。但是在这之后我得到了一个新的要求,比如,

有一个数组string[] BranchIds = {"1","2","3"}

var a =_abc.GetRoutes(0)
    .Where(r => BranchIds.Contains(r.StringBranchIds))
    .ToList();

如果这段代码中的StringBranchIds也是一个逗号分隔的字符串呢?

我尝试过类似的方法:

var a =_abc.GetRoutes(0)
    .Where(n => BranchIds.Contains((n.StringBranchIds.Replace(" ", "")
        .Split(',')
        .Select(m => Convert.ToInt32(m))
        .ToArray()).ToString()));

但是不行。

Contains 里面我只能提供字符串。 Linq 是这样工作的吗?

我是 Linq 的新手,请帮帮忙!

【问题讨论】:

  • 什么是GetRoutes
  • 条件是什么?如果他们都在BranchIds或任何?
  • @Ofir IEnumerable
  • BranchId in this code is also a comma separated string BranchId 的外观以及r.BranchId 中的值是什么
  • 能否请您提供一些示例?让abc.GetRoutes(0) 返回,说"3,1" 是正面还是负面的例子(BranchIds = {"1","2","3"})?如果abc.GetRoutes(0) 返回"2,4"部分交集)怎么办?

标签: c# linq


【解决方案1】:

Contains 方法询问 单个 值是否在更宽的序列/列表中。你没有那个;你有(对于每个分支):

  • StringBranchIds 反对“路线”,我们可以相对轻松地将其转换为平面列表
  • BranchIds 是我们正在测试的固定列表

与包含无关

假设你的意思是“任何交叉点”,那么这将是这样的:

var a =_abc.GetRoutes(0).Where(n =>
   n.StringBranchIds.Replace(" ", "").Split(',').Any(
        id => BranchIds.Contains(id)
   ));

这是做什么的:

  • StringBranchIds 拆分成小块
  • 对于每一个,测试它是否包含在BranchIds

但是请注意,这不是在性能方面是最佳的 - 大量 O(N) 测试。如果BranchIds 相对较小,您可能会没事(任何O(1) “改进”可能O(N),对于小的N)。如果BranchIdslong,您可以将其预处理为HashSet<string> 等。

请注意,我没有将任何内容解析为 int - 没有必要,这对您的表现没有帮助。

此外,您应该考虑将StringBranchIds 预处理为适合测试的东西;这不一定涉及很多变化。例如,从这里:

public string StringBranchIds {get;set;}

我们可以改成:

private string _stringBranchIds;
public string StringBranchIds {
    get { return _stringBranchIds; }
    set {
        if(value != _stringBranchIds) {
            _stringBranchIds = value;
            _splitIds = null; // only if actually a change
        }
    }
}
private string _splitIds;
internal string[] GetSplitIds() {
    return _splitIds ?? (_splitIds =
        (_stringBranchIds ?? "").Replace(" ", "").Split(','));
}

现在我们只需将方法更改为使用n.GetSplitIds() 而不是n.StringBranchIds,它会返回相同的 id 数组,直到值更改。比每次拆分便宜得多。

【讨论】:

  • 虽然顾名思义,"1""2" 等形式的 ID 至少在 BranchIds 数组中应该是 ints。
  • @TheLethalCoder 这里已经有足够的开销了;正在执行的测试中没有任何内容需要我们解析它;但是是的,如果 BranchIdsint[](或类似的),那么在我以后的编辑中(按 F5)我们可以将 GetSplitIds 更改为也返回 int[],并在那里添加解析
  • 我同意此处显示的示例不需要它,但是,它似乎应该是 int 以供以后使用,可能是正确的
  • 在问题中,他问“如果这段代码中的StringBranchIds也是逗号分隔的字符串怎么办?”。这意味着他有一个字符串列表,每个字符串都是逗号分隔的整数字符串。请参阅考虑到这一点的我的答案,并随时将其与您的合并。
  • @kall2sollies 感谢您的支持,但在这个问题中,我的意思只是 - 一个字符串,其中包含以逗号分隔的整数。
【解决方案2】:

随你拆分逻辑

var a =_abc.GetRoutes(0).Where(r =>
          !r.StringBranchIds.Replace(" ", "").Split(',').Except(BranchIds).Any()).ToList();

这将只返回所有StringBranchIds 包含在BranchIds 中的路由。

【讨论】:

    猜你喜欢
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    相关资源
    最近更新 更多