【问题标题】:Linq find first value of list in other listLinq在其他列表中查找列表的第一个值
【发布时间】:2012-12-19 20:45:49
【问题描述】:

一个看似简单的问题: 我有一个字符串列表(从属性文件中读取):

IList<string> defaultValues = new List<string> {"0458","0309"};

还有一些对象的另一个列表,每个对象都有一个字符串类型的属性:

IList<Token> tokens = new List<Token>
{
    new Token {DisplayValue = "0123"},
    new Token {DisplayValue = "0309"},
    new Token {DisplayValue = "0203"},
    new Token {DisplayValue = "0458"},
    new Token {DisplayValue = "0911"}
};

public class Token
{
   public string DisplayValue { get; set; }
}

现在我想获取 DisplayValue 与 defaultValues (0485) 的第一个元素匹配的标记元素。如果没有找到 DisplayValue 为 0485 的元素,则 defaultvalues 中的第二个元素应匹配 (0309),依此类推。

defaultValues 列表可以是动态的,因此可以添加更多值,并且总是第一个条目应该具有优先权。

所以 defaultValues 列表是字符串的优先级列表,索引越低优先级越高。 在上面的例子中,结果应该是“0458”。

我可以这样做:

string result = string.Empty;

foreach (var searchValue in defaultValues)
{
    if (tokens.Any(token => token.DisplayValue == searchValue))
    {
        result = searchValue;
    }   
}

但我认为这样的事情可以更优雅地完成,并且不需要 foreach ...

【问题讨论】:

    标签: .net linq list lambda


    【解决方案1】:

    在这种情况下,使用 Any 是 O(n^2),这可能不是最高效的。可能最好的方法是执行 GroupJoin (改为 O(n)),然后选择匹配的第一个令牌。请记住,GroupJoin 仅在完全匹配的键上执行此操作,因此如果您正在寻找比较或子字符串搜索,则必须找到其他方法。

    defaultValues
        .GroupJoin(
            tokens, // matching 0:n tokens per default value
            defVals => defVals, // key selector for our left source
            tks => tks.DisplayValue, // key selector for our right source
            (defVal, tks) => tks.FirstOrDefault()) // result selector for our matches
        .FirstOrDefault(match => match != null)
    

    这样做的好处是只遍历每个集合一次,并将所有标记与相应的DefaultValue 匹配(因此每个默认值可以有多个匹配项)。你可以做defaultValues.FirstOrDefault(x =&gt; tokens.Any(t =&gt; t == x)),但你会遇到同样的问题(可能复杂度为 O(n^2))。从这里,您可以检查它是否为 null(使用 null 合并)并在初始化为 new Token { DisplayValue = string.Empty } 的 Token 中添加一个名为 Empty 的静态常量。之后你可以这样做:

    (defaultValues
        .GroupJoin(
            ...
        .FirstOrDefault(match => match != null) ?? Token.Empty).DisplayValue
    

    【讨论】:

      【解决方案2】:

      基本上你需要从你的 Linq/Lambada 结果中寻找一个投影

      我会尝试这样的事情:

      var macthes = tokens.Any(t => t.DisplayValue.In(defaultValues))
                    .Select(y =>y.DisplayValue);
      

      【讨论】:

        猜你喜欢
        • 2020-10-04
        • 2022-01-04
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-08
        • 1970-01-01
        相关资源
        最近更新 更多