【问题标题】:Evaluate equality among n variables, without check each pair评估 n 个变量之间的相等性,而不检查每一对
【发布时间】:2016-02-23 09:51:15
【问题描述】:

不确定这是否可能,没有对 N 个变量中的每一个进行全面比较。

对于 int 或 float,我可以使用简单的数学来确定数字是否相同;求和,然后除以元素的数量。

但是如果我想检查 3 个变量是否包含相同的字符串,我不能使用这种方法。 可能 var1 和 var2 相同,或者 var3 和 var 1 相同,并且 var2 和 var3 也可能相同。据我了解,除非您对每个变量进行比较,否则无法知道该变量的内容是否相同。

我错过了什么还是有更简单的方法?

3 个变量的示例:

string var1 = "hello";
string var2 = "there";
string var3 = "hello";

if (var1 == var2 || var1 == var3 || var2 == var3)
    //got a duplicate
else
    //all are different

假设比较 20 个变量,写一个比较语句需要很长时间。

对我来说,这听起来类似于搜索算法,我可以应用与排序二分搜索相同的概念吗?

【问题讨论】:

  • 尝试将它们添加到列表中
  • 序列是否相同无关紧要;尽管我看到了求和然后除以元素数量的数学缺陷。 5,5,5 将得到 15,除以 3 将匹配第一个变量 (5),但如果序列是 5,4,6,这将是相同的;因为它会除以 3 并得到 5,作为第一种情况,但这里我们没有重复。

标签: c#


【解决方案1】:

把它们放在一个集合中,你的生活就会轻松很多。

一种微妙但有效的方法是使用HashSet<>

string[] collection = { var1, var2, var3 };
var set = new HashSet<string>();
bool noDuplicate = collection.All(set.Add);

HashSet.Add 返回true,如果该项目可以被添加(如果它不存在)。所以这个集合不允许重复。 Enumerable.All 将在第一个 false 上停止枚举。如果所有都是唯一的,所有都可以添加到集合中,noDuplicate 将是true

【讨论】:

  • 这似乎是最好的解决方案;它快速、简单且无需编写太多代码。谢谢
  • 这不检查是否只有第一个元素有重复项?
  • @DovydasSopa:当然,所以我修改了我的答案:)
  • @newbiez:是的,您可以将集合传递给HashSet 的构造函数。所以另一种方法是使用var set = new HashSet&lt;string&gt;(collection); bool noDuplicate=collection.Length==set.Count;。但我更喜欢 LINQ 方法,因为它会在发现重复项后立即停止。
  • 或者你问HashSet&lt;T&gt;是否支持collection initializer语法?是的,确实如此。
【解决方案2】:

你可以试试这样的:

List<string> l = new List<string>() {"a", "b", "a"};
bool isDuplicate = l.GroupBy(i => i).Any(x => x.Count() > 1);

【讨论】:

    【解决方案3】:

    将所有元素放入列表中,然后比较普通列表元素计数是否与 dinstict 相同:

    string var1 = "hello";
    string var2 = "there";
    string var3 = "hello";
    string[] values = new [] { var1, var2, var3 };
    if (values.Length != values.Distinct.Count()) {
        // Got a duplicate.
    } else {
        // All are different.
    }
    

    【讨论】:

    • 谢谢;虽然这种方式有两个操作:一个是添加到列表中,另一个是搜索每个重复项。不确定 distinct 函数在内部是如何工作的,但它的复杂度似乎是 2n
    • @newbiez 相当于 TimSchmelter 的解决方案 - referencesource.microsoft.com/#System.Core/System/Linq/…
    • @Eugene Podskal 这并不完全等同。 TimSchmelter 的解决方案将在找到第一个重复项时停止。此解决方案需要遍历所有项目。
    • @DovydasSopa 是的,我的意思是它不会是 O(n*n),而是摊销 O(n)。它在内部使用“Hash”Set,尽管它必须遍历所有项目。
    【解决方案4】:
        string var1 = "hello";
        string var2 = "there";
        string var3 = "hello";
        string var4 = "hello";
        string var5 = "there";
        string var6 = "hello";
        List<string> strings = new List<string>() { var1, var2, var3,var4,var5,var6 };
        var grouped = strings.GroupBy(x => x);
        Dictionary<string,int> stringAndCount = grouped.ToDictionary(x => x.Key, x => x.Count());
    

    字符串(键)是变量的内容,int值是你的列表中有多少个变量等于那个字符串键。

    Key: hello, Value: 4
    Key: there, Value: 2
    

    编辑:

    如果你只是想知道是否有重复:

    List<string> strings = new List<string>() { var1, var2, var3,var4,var5,var6 };
    
    bool hasDupes = strings.Count != (new HashSet<string>(strings)).Count;
    

    【讨论】:

    • 谢谢。所以你先创建一个列表,然后再创建一个字典?这可能行得通,但在时间和空间方面,开销很大
    • @newbiez 它工作,哈哈。仅当您想知道有多少重复项时才这样做。如果你真的不介意,HashSet 可以做到。
    • @newbiez 另外,我不确定您认为哪个部分有开销,而是 Dictionary is also a hash 。加上 GroupBy 实现了 IENumerable,它加载得很慢。我不会试图争论,因为虽然我担心更明显的开销,但 C# 不像 C,因为 JIT / IL 和其他东西,更简单的技术在空间和时间方面更优化。
    • 是的,我对我有多少副本并不感兴趣。我需要知道是否只有重复;并采取相应行动:) 我正在研究我调用的函数在多个实例中被多次调用的场景;这会导致每次创建 2 个对象......所以我试图获得一个生成尽可能少的对象的解决方案;提高效率(我处理大量数据,所以斗争是真实的)
    • @newbiez 编辑了我对一些可能更有用的答案,尽管它可能已经在本页的其他地方得到了回答(编辑:比蒂姆的答案复杂一点:P)
    猜你喜欢
    • 1970-01-01
    • 2020-05-28
    • 2016-01-16
    • 1970-01-01
    • 2020-05-24
    • 2015-01-08
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多