Query values

The declarations and entries in the two_Dict dictionary are created as given:

Dictionary<string, List<string>>two_Dict = new Dictionary<string, List<string>>();
List<string> list; 

if (!two_Dict.TryGetValue(d.ToString(), out list))
{
    two_Dict.Add( d.ToString(), list = new List<string>());
    list.Add(possibility_cell_list[0]);
    list.Add(possibility_cell_list[1]);
}

      

Example entries in two_Dict

:

two_Dict["5"] Count = 2 [0]: "A2"  [1]: "D2"
two_Dict["6"] Count = 2 [0]: "A2"  [1]: "D2"

      

I am looking to form a linq query to get keys that have the same entries in the dictionary two_Dict

. Any help would be appreciated.

+3


source to share


3 answers


You can use a pretty simple expression with linq:

var keys = from kvp1 in two_dict
           where two_dict.Any(kvp2 => kvp2.Key != kvp1.Key
               && kvp2.Value.SequenceEqual(kvp1.Value))
           select kvp1.Key;

      

However, this does not give the best performance as it will search the entire dictionary n

once, where n

is the number of entries in the dictionary.

You can get slightly better performance if you just look at the items that have been viewed so far. So you only get half the dictionary n

times on average , so in theory it's twice as fast. Unfortunately, I don't think there is a good way to do this using linq.



public static IEnumerable GetDuplicates(IDictionary<string, List<string>> dict)
{
    var previousItems = new List<KeyValuePair<string, List<string>>>(dict.Count);
    var matchedItems = new List<bool>();
    foreach (var kvp in dict)
    {
        var match = previousItems.Select((kvp2, i) => Tuple.Create(kvp2.Key, kvp2.Value, i)).FirstOrDefault(t => kvp.Value.SequenceEqual(t.Item2));
        if (match != null)
        {
            var index = match.Item3;
            if (!matchedItems[index])
            {
                yield return match.Item1;
                matchedItems[index] = true;
            }
            yield return kvp.Key;
        }
        else
        {
            previousItems.Add(kvp);
            matchedItems.Add(false);
        }
    }
}

      

You would call the function like this:

var keys = GetDuplicates(two_dict);

      

+1


source


How about this



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, List<string>> two_Dict = new Dictionary<string, List<string>>();
            var keyIndex = two_Dict.Keys.AsEnumerable()
                .Select((x, i) => new { index = i, value = x })
                .ToList();

            var result = (from key1 in keyIndex
                          from key2 in keyIndex
                          where key1.index > key2.index 
                          where AreEqual(two_Dict[key1.value],two_Dict[key2.value])
                          select new {key1 = key1.value, key2 = key2.value}).ToList(); 
        }
        static bool AreEqual<T>(List<T> x, List<T> y)
        {
            // same list or both are null
            if (x == y)
            {
                return true;
            }

            // one is null (but not the other)
            if (x == null || y == null)
            {
                return false;
            }

            // count differs; they are not equal
            if (x.Count != y.Count)
            {
                return false;
            }
            x.Sort();
            y.Sort();
            for (int i = 0; i < x.Count; i++)
            {
                if (!x[i].Equals(y[i]))
                {
                    return false;
                }
            }
            return true;
        }
    }
}
​

      

0


source


All linq, no duplicate result, but also, be careful, no null checks:

            var res = from k1 in dict.Keys
                from k2 in dict.Keys
                where string.Compare(k1, k2) == -1 && 
                dict[k1].Count == dict[k2].Count && !dict[k1].Any(x => !dict[k2].Contains(x)) && !dict[k2].Any(x => !dict[k1].Contains(x))
                select new { k1, k2 };

      

0


source







All Articles