【问题标题】:ContainsValue with Dictionary(Of String, Items)包含值与字典(字符串,项目)
【发布时间】:2020-06-18 13:04:43
【问题描述】:

如何知道具有多个值的字典是否包含特定值?

'Create dictionary
Dim testDictionary As New Dictionary(Of String, Items)

'Code to fill dictionary
'.......................
'.......................
'.......................

'Test if a specific value is contained in dictionary
Dim testValue as String = "TEST"
testDictionary.ContainsValue(testValue) 'This doesn't work

Public Class Items
    Public Property Property1 As String
    Public Property Property2 As String
    Public Sub New()
    End Sub
End Class

【问题讨论】:

  • 您应该使用 Key 来确定 Dictionary 是否包含特定的 Value,在这种情况下,它也是类对象的 Property 值。你用钥匙干什么?无论如何,您可以检查 Values 集合,例如 Dim theItem = testDictionary.Values.OfType(Of Items).FirstOrDefault(Function(i) i.Property1.Equals("TEST") OrElse i.Property2.Equals("TEST"))。如果您只需要测试是否存在,您可以使用Any() 而不是FirstOrDefault()。您应该使用密钥。或其他类型的集合。
  • 什么值?这是一个字符串,但字典包含Itemss。 testValue 应该出现在 Property1 还是 Property2 中?或者两者兼而有之?还是完全不同的东西?
  • 如果您在Dictionary 中寻找值(而不是键),那么您应该认真考虑一个普通的Dictionary 是否是正确的数据结构。 (可能最终您会得出结论,但搜索值是一个巨大的危险信号。)

标签: vb.net dictionary contains


【解决方案1】:

如果您可以定义如何确定字典是否包含该字符串,则将该逻辑传递给Enumerable.Any

Dim testValue As String = "TEST"

Dim contains = testDictionary.Any(Function(kvp) kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue)
If contains Then
    Dim containsEntries = testDictionary.Where(Function(kvp) kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue)
End If

由于您在 Any 和 Where 中重复使用它,因此您可以声明一次谓词

Dim predicate =
    Function(kvp As KeyValuePair(Of String, Items))
        Return kvp.Value.Property1 = testValue OrElse kvp.Value.Property2 = testValue
    End Function
Dim contains = testDictionary.Any(predicate)
If contains Then
    Dim containsEntries = testDictionary.Where(predicate)
End If

这只是硬编码为这些属性 Property1 和 Property2。

(如果你想要实体,你真的不需要 Any;我只是认为 Any 用布尔值回答了你的问题 "How to know if..."

如果要检查所有公共实例字符串属性,可以使用反射

Dim predicate =
    Function(kvp As KeyValuePair(Of String, Items))
        Return GetType(Items).
            GetProperties(Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance).
            Where(Function(pi) pi.PropertyType Is GetType(String)).
            Aggregate(False, Function(pi1, pi2) pi1 Or (pi2.GetValue(kvp.Value) = testValue))
    End Function
Dim containsWith = testDictionary.Any(predicate)
If containsWith Then
    Dim containsEntries = testDictionary.Where(predicate)
End If

【讨论】:

  • 非常感谢,@djv。太棒了。再问一个问题:containsEntries 类型是 IEnumerable,如何获取它拥有的元素个数?我发现 IEnumerable 不支持 Count 属性。要使用 Count 属性,ICollection 类型是必需的,但这会在 Where 扩展名中产生错误。
  • @Queeng4 it certainly does。这是一个带有谓词的overload。事实上,我给你的同一个谓词也会起作用。 testDictionary.Count(predicate)containsEntries.Count()
  • 是否有必要进行任何导入?由于 Count 没有作为该对象的属性出现,我无法使用 containsEntries.Count() 获取元素的数量。
  • 抱歉,这是一个 VB.NET 问题。试试testDictionary.AsEnumerable().Count(predicate)。见this question。基本上 VB.NET 无法区分 Count 属性和 Enumerable.Count 扩展。这在 C# 中不会发生。我之前的评论未经测试且错误:/
  • 好的,没问题。它现在适用于该提示。我会投票赞成你的答案是正确的。我期望的信息少于您提供给我的信息。很有用。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2016-03-21
  • 2013-03-04
相关资源
最近更新 更多