一个看似简单的问题: 我有一个字符串列表(从属性文件中读取):
IList<string> defaultValues = new List<string> {"0458","0309"};
和一些对象的列表,每个对象都具有string类型的属性:
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 List可以是动态的,因此可以添加更多值,并且始终第一个条目应具有优先级。
因此defaultValues列表是字符串的优先级列表,索引越低,优先级越高。 在上面的示例中,结果应为“0458”。
我可以这样做:
string result = string.Empty;
foreach (var searchValue in defaultValues)
{
if (tokens.Any(token => token.DisplayValue == searchValue))
{
result = searchValue;
}
}
但是我觉得这样的事情可以更优雅地完成而且没有预告......
答案 0 :(得分:2)
在这种情况下,使用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 => tokens.Any(t => t == x))
,但您遇到了同样的问题(可能存在O(n ^ 2)复杂度)。从这里开始,您可以检查它是否为空(使用空合并)并在令牌中添加一个名为Empty
的静态常量,初始化为new Token { DisplayValue = string.Empty }
。之后你可以这样做:
(defaultValues
.GroupJoin(
...
.FirstOrDefault(match => match != null) ?? Token.Empty).DisplayValue
答案 1 :(得分:0)
基本上,您需要从Linq / Lambada 结果中查找投影。
我会尝试这样的事情:
var macthes = tokens.Any(t => t.DisplayValue.In(defaultValues))
.Select(y =>y.DisplayValue);