【问题标题】:Prevent duplicate variables of the objects added as Values in a dictionary c#防止在字典c#中作为值添加的对象的重复变量
【发布时间】:2021-12-18 17:09:53
【问题描述】:

我的Individual 班级中有一个Dictionary<int,int>

 public class Individual
    {
       Dictionary<int,int> pattern = new Dictionary<int,int>();
    }

我想在我的 population 字典中添加一个 &lt;int,Individual&gt; 对:

Dictionary<int,Individual> population = new Dictionary<int, Individual>();

当且仅当字典中没有其他 Individual 具有类似的 pattern 变量。

我目前的方法是天真地迭代每个Individual 中的每个pattern 已经存在于population,但我相信使用不同的方法可以更快地完成。

public bool same_dict(Dictionary<int, int> p1, Dictionary<int, int> p2)
//Meant to compare patterns
{
    if (p1.Count != p1.Count) return false;
    foreach (var feature in p1)
    {
        if (p2.ContainsKey(feature.Key))
        {
            if (feature.Value != p2[feature.Key]) return false;
        }
        else return false;
    }
    return true;
}

public bool matched is_duplicated(Individual ind, Dictionary<int, Individual> pop)
{
//Meant to compare Individuals
    foreach (var ind2 in pop)
    {
        if (same_dict(ind.pattern, ind2.Value.pattern))
        {
            return true;
        }
    }
    return false;
} 

我必须使用ints 作为population 字典的键,因为我使用它来链接Individual 对象与程序的其他部分。 pattern 字典可以包含任意数量的键:值对,这就是我验证它们的 .Count 属性是否相同的原因。

【问题讨论】:

    标签: c# performance dictionary hash duplicates


    【解决方案1】:

    我不确定我是否正确理解了您的问题,但是...

    当且仅当字典中没有其他个人具有 相似模式变量

    “类似的模式变量”意味着,我认为,两个IndividualPattern 字典,其中包含相同的键和值(不知道,它可以有多少“模式”商店)。

    所以我尝试使用 LINQ 的.Any() 扩展方法来检查population 字典中的任何IndividualPattern 字典与添加的Individual 具有相同的键和值。听起来很复杂,所以这里是代码示例(控制台):

    public class Individual
    {
        public Dictionary<int, int> Pattern { get; set; } = new Dictionary<int, int>();
    }
    
    static void Main()
    {
        var population = new Dictionary<int, Individual>();
        var key = 0;
    
        for (; key < 5; key++) // Fill population with some Individuals
        {
            var individual = new Individual();
            individual.Pattern.Add(key + 1, key + 2);
    
            population.Add(key, individual);
        }
    
        // Print current population:
        Console.WriteLine("Population Dictionary:");
        foreach (var kvp in population)
            Console.WriteLine(kvp.Key + ": " +
                              string.Join(" | ", kvp.Value.Pattern.Select(pattern => pattern.Key + "," + pattern.Value)));
    
        // Creating new Individuals, which we will try to add to population
        var newIndividual1 = new Individual();
        newIndividual1.Pattern.Add(5, 6);
        var newIndividual2 = new Individual();
        newIndividual2.Pattern.Add(5, 5);
        var newIndividual3 = new Individual();
        newIndividual3.Pattern.Add(8, 9);
    
        Console.WriteLine();
        Console.WriteLine("Adding new Individuals:");
    
        if (AddIndividual(population, key, newIndividual1))
            key++;
    
        if (AddIndividual(population, key, newIndividual2))
            key++;
    
        if (AddIndividual(population, key, newIndividual3))
            key++;
    
        Console.ReadKey();
    }
    
    static bool AddIndividual(Dictionary<int, Individual> population, int newKey, Individual newIndividual)
    {
        // Compare each Individual in population with newIndividual
        if (!population.Any(p => newIndividual.Pattern.Keys.Any(k => p.Value.Pattern.ContainsKey(k)) &&
                                 newIndividual.Pattern.Values.Any(v => p.Value.Pattern.ContainsValue(v))))
        {
            population.Add(newKey, newIndividual);
            Console.WriteLine("Individual with pattern " +
                              string.Join(" | ", newIndividual.Pattern.Select(pattern => pattern.Key + "," + pattern.Value)) +
                              " successfully added to Population Dictionary.");
    
            return true;
        }
        else
        {
            Console.WriteLine("Individual with pattern " +
                              string.Join(" | ", newIndividual.Pattern.Select(pattern => pattern.Key + "," + pattern.Value)) +
                              " already exists in Population Dictionary.");
    
            return false;
        }
    }
    

    输出样本:

    编辑。

    您可以将.Any 方法的键值比较替换为.SequenceEqual

    if (!population.Any(p => p.Value.Pattern.OrderBy(kvp => kvp.Key).SequenceEqual(newIndividual.Pattern.OrderBy(kvp => kvp.Key))))
    {
        population.Add(newKey, newIndividual);
    }
    

    【讨论】:

    • 你的问题是对的。如果一个人的模式字典具有相同的键和相同的值,则他们与另一个人相似。所述字典可以包含任意数量的键、值对。我首先验证两个字典的计数是否相等,从而加快了这个过程。如果是,我会遍历每个键:值对。您的解决方案有效,并且与我正在做的非常相似,但使用“.Any”而不是手动迭代。这是否意味着没有更快的方法在字典中查找重复项?我期待某种哈希表解决方案,但我无法想象它是这样的。
    • 您对此有性能问题吗?为什么需要更快?
    • 您还可以将.Any 的比较键和值替换为.SequenceEqual。例如检查编辑。
    猜你喜欢
    • 1970-01-01
    • 2022-10-13
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多