【问题标题】:C# Determine if Dictionary Contains All of a Set of ValuesC#确定字典是否包含一组值的所有
【发布时间】:2017-02-17 10:34:51
【问题描述】:

我有以下字典:

Dictionary<string, ArrayList> vertices = new Dictionary<string, ArrayList>();
vertices.Add("Key1",stringarray1);
vertices.Add("Key2",stringarray2);
vertices.Add("Key3",stringarray3);

现在我想弄清楚如何检查字典的每个其他键(如"Key2""Key3"),如果它们的值包含来自"Key1" 值的一个或所有值( ArrayList),但它不起作用。这可能非常简单,但我无法理解

var values = (ArrayList)vertices["Key1"];
foreach (var val in vertices)
{
    if (val.Key != "Key1" && val.Value.Contains(values))
    {
        //do something here
    }
}

【问题讨论】:

  • 不确定是否是您的问题,但默认情况下字符串比较区分大小写。使用val.Key != "Key1" &amp;&amp;
  • 你在arrayList中存储的数据是什么?您使用这种结构的任何具体原因?

标签: c# dictionary arraylist


【解决方案1】:

您不能将集合传递给 contains 方法,而是将其传递给单个元素。所以你需要遍历 key1 数组中的元素并检查另一个数组是否也包含它。

var key1Val = vertices["key1"];
 foreach (var val in vertices)
        {
            if(val.Key != "key1")
            {
               bool exist = false;
               foreach (var element in val.Value) {
                      if(key1Val.Contains(element)){
                            exist = true;
                            break;
                      }
                 }
                  if(exist){        /*do stuff*/}
                //do something here
            }
        }

【讨论】:

  • 您标记为有用的答案与我的答案具有完全相同的时间复杂度,因此我对您认为如何提高效率感到有些困惑。我承认它使用了更简洁的语法(我试图合并你所写的),但不要让你误以为它的执行速度更快。
  • 在最坏的情况下,您总是需要将非 key1 列表中的每个元素与 key1 列表中的所有元素进行比较。您可以做的唯一优化是在您击中比赛后取消检查(这就是我所做的)。使用 Linq 表示法不会改变这一事实。
【解决方案2】:
var key1Values;
if (!vertices.TryGetValue("Key1", out key1Values)) {   
   return; 
}

foreach(KeyValuePair<string, ArrayList> entry in vertices)
{
    if((entry.Key == "Key2" || entry.Key == "Key3") && entry.Value.Any(item => key1Values.Contains(item) )
    {
       //do some work
    }
}

【讨论】:

    【解决方案3】:

    问题是您将错误的东西传递给ContainsContains 应该接收要在集合中查找的项目,但您传递的是整个集合。因为您使用的是ArrayList,其中项目存储为object,所以您没有收到编译时错误,但它不起作用(并且使用object比较项目来检查引用.

    您可以使用 Linq 这样做:

    string key = "Key1";
    var key1Collection = vertices[key].Cast<object>().ToList();
    foreach(var item in vertices.Where(x => x.Key != key ))
    {
        //If you want that all the items of the collection will be in the "Key1" collection:
        if(item.Value.Cast<object>().All(x => key1Collection.Contains(x))
        {
             //Do stuff
        }
    
        //Or if you want that at least 1 of the items of the collection will be in the "Key1" collection:
        if(item.Value.Cast<object>().Any(x => key1Collection.Contains(x))
        {
             //Do stuff
        }
    }
    

    如果您将数据结构从 ArrayList 更改为 List&lt;TheTypeOfYourItems&gt;,那么您将不需要所有 .Cast&lt;object&gt;

    【讨论】:

    • 我需要弄清楚哪个确切的键返回真,哪个不是。因为我需要做一些手动操作。你能帮忙吗?
    • @Srini - 还有你使用ArrayList 的原因是什么?你放在那里的实际数据是什么?
    • 谢谢,这很有魅力。我现在修改了我的数据结构为链表,之前选错了。
    • @Srini - 我认为你可以选择普通的List&lt;SomeType&gt; - 最直接和简单:)
    【解决方案4】:

    这个怎么样:

    var keys =
        vertices
            .Where(y => y.Key != "Key1")
            .Where(y => vertices["Key1"].Cast<string>().Intersect(y.Value.Cast<string>()).Any())
            .Select(x => x.Key);
    

    或者,如果您将ArrayList 更改为List&lt;string&gt;

    var keys =
        vertices
            .Where(y => y.Key != "Key1")
            .Where(y => vertices["Key1"].Intersect(y.Value).Any())
            .Select(x => x.Key);
    

    【讨论】:

    • 如果我错了,请纠正我,但您不是将字典中的每个列表都与其他列表进行比较吗? OP 只是要求将第一个列表与所有其他列表进行比较。例如,我们不想找到列表 2 和 3 的交集,因为这是不必要的。
    • 还会导致重复匹配,因为 1-2 交点与 2-1 交点相同。
    • @LucasKot-Zaniewski - 你是对的。我已经确定了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多