我有两个字典,都属于Dictionary<string, List<List<string>>
类型。
我想从词典1中选择与词典2中的值/条目匹配的条目范围。
例如字典1的键为01, 01.1
,而字典2的键为01, 01.1.
则具有匹配值1
首先,我从字典2的键1处获得条目,如下所示:
var dictList = (from entry in DbDict
where entry.Key == id.ToString() // id = 1
select entry).ToList();
我试图通过linq选择这些,如下所示:
var matchingEntries = (from entry in ExcelDict
where ExcelDict.Keys.Equals(dictList[0].Value)
select entry).ToList();
并尝试了更多方法,但不会返回任何结果。
如何从字典1中获得值对的范围,字典1的键与字典2中的值匹配?
编辑1:
Dictionary 1:
Key Value
01 "these", "are"
..., ...
01.1 "just", "some"
..., ...
02 "sample", "values"
..., ...
Dictionary 2:
Key Value
1 "01", "01.1"
"foo", "bar"
..., ...
2 "02", "02.21"
"value1" "value2"
编辑2:
预期输出:
"01", "01.1"
"foo", "bar"
Edit3:
注释中要求的可编译输入。这正是我要处理的结构:
var dict1 = new Dictionary<string, List<List<string>>>();
dict1.Add("01", new List<List<string>> { new List<string> { "these" }, new List<string> { "are" } });
dict1.Add("01.1", new List<List<string>> { new List<string> { "just" }, new List<string> { "some" } });
dict1.Add("02", new List<List<string>> { new List<string> { "sample" }, new List<string> { "values" } });
var dict2 = new Dictionary<string, List<List<string>>>();
dict2.Add("1", new List<List<string>> { new List<string> { "01", "01.1" }, new List<string> { "foo", "bar" } });
dict2.Add("2", new List<List<string>> { new List<string> { "02", "value1" }, new List<string> { "02.21", "value2" } });
编辑4:
对不起,您的回复很晚。高朗·戴夫(Gaurang Dave)在评论中的建议和被接受的答案都对我有用。谢谢大家的帮助!
答案 0 :(得分:4)
您写道:
我想从字典1中选择匹配的条目范围 字典2中的值/条目。
在Edit2的输出中,您似乎想从Dictionary 2中获取值。您对键并没有做任何事情。每个值都是一个List<List<string>>
。在您的示例中,键1的值的第一列表中的所有字符串在字典1中都有对应的键。显然,这是确定完整值在输出中的条件。
具有键2的值的第一个列表包含一个不是字典1中的键的元素。因此,输出中没有任何值。
不清楚:如果第二个列表而不是第一个列表匹配,该怎么办?
Key Value
3 "foo", "bar"
"01", "01.1"
这也是您的最终结果吗?
不清楚:您是否想要List<List<string>>
作为结果,还是想要一个具有所有匹配值的大List<string>
?重复值呢?
假设您只想检查列表列表中的第一个列表:
我们将仅查看字典2中的值,这些键将被丢弃。然后从该值集合的每个列表中选取第一个(如果有),并作为一个单独的属性记住完整列表。
当然,空列表不应出现在最终结果中,因此,我们仅保留那些具有第一个元素的列表:
// Only use the values of dictionary 2:
IEnumerable<List<List<string>>> dict2Values = dictionary2.Values
// then for easy comparison extract the first list
var separatedFirstList = dict2Values.Select(listOfLists=> new
{
FirstList = listOfLists.FirstOrDefault(), // this is a List<string> or null
AllLists = listOfLists, // original List<List<string>> where FirstList is the first
})
// keep only the elements that have a first list:
.Where(stringListWithFirstElement => stringListWithFirstElement.FirstList != null);
现在,我们已将示例字典转换为:
{
FirstString = {"01", "01.1"},
FullList = {"01", "01.1"}, {"foo", "bar"}, {...}, {...},
},
{
FirstString = {"02", "02.21"},
FullList = {"02", "02.21"}, {"value1" "value2"}, ...
},
{
FirstString = ...,
FullList = ...,
},
...
根据此序列,我们只想保留FirstString
中的WHERE ALL元素是Dictionary 1
的键:
IEnumerable<string> keysDictionary1 = dictionary1.Keys;
var matchingItems = separatedFirstList
.Where(item => item.FirstList.All(txt => keysDictionary1.Contains(txt));
您会看到“哪里”和“全部”。
结果:
{
FirstString = {"01", "01.1"},
FullList = {"01", "01.1"}, {"foo", "bar"}, {...}, {...},
},
...
具有FirstString = {"02", "02.21"}
的那个元素被删除,因为不是firstString的所有元素都在字典1中,因此
最后:摆脱FirstString:
List<List<String>> finalResult = matchingItems
.Select(matchingItem => matchingItem.FullList);
或者如果您希望结果为一个List<String>
:
List<string> finalResult = matchingItems.SelectMany(matchingItem => matchingItem.FullList);
TODO:考虑创建一个大的LINQ语句。由于中间步骤使用延迟执行,因此我不确定这是否会提高性能。但是,我确信它会降低可读性。
答案 1 :(得分:2)
似乎您正在使用linq寻找join
:
var result = from d1 in dict1
join d2 in dict2
on double.Parse(d1.Key) equals double.Parse(d2.Key)
select d2.Value;
在上述查询中,我们通过相等的键(通过将键解析为数字)来连接两个字典,并为每个匹配项从第二个字典中选择Value
作为匹配项的结果。
答案 2 :(得分:0)
这将为您提供想要的东西:
var result = dict2
.Select(kvp => kvp.Value)
.Where(list => list.Where(l => l.Join(dict1.Keys, s1 => s1, s2 => s2, (s1, s2) => s1).Count() == l.Count).Count() > 0)
.ToList();