Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当三个变量中的任何一个都可以是通配符时,检查这三个变量是否相等的优雅方法是什么?_C#_Puzzle_Equality - Fatal编程技术网

C# 当三个变量中的任何一个都可以是通配符时,检查这三个变量是否相等的优雅方法是什么?

C# 当三个变量中的任何一个都可以是通配符时,检查这三个变量是否相等的优雅方法是什么?,c#,puzzle,equality,C#,Puzzle,Equality,假设我有3个char变量,a,b和c 每个字符都可以是'0',这是一个特例,意味着它匹配每个字符 因此,如果a是'0',我只需要检查b==c 我想检查a==b==c,但发现c中的实现变得混乱而冗长 你能提供什么创造性的或漂亮的解决方案吗 更新 对于性能驱动,采用Erik A.Brandstadmoen的方法。 为了简单起见,使用M4N的方法,我也做了一些修改:!(query.Any() var a = '1'; var b = '0'; var c = '1'; var chars = new

假设我有3个
char
变量,
a
b
c

每个字符都可以是
'0'
,这是一个特例,意味着它匹配每个字符

因此,如果a是
'0'
,我只需要检查
b==c

我想检查a==b==c,但发现c中的实现变得混乱而冗长

你能提供什么创造性的或漂亮的解决方案吗

更新

对于性能驱动,采用Erik A.Brandstadmoen的方法。 为了简单起见,使用M4N的方法,我也做了一些修改:
!(query.Any()

var a = '1';
var b = '0';
var c = '1';

var chars = new List<char> { a, b, c };
var filtered = chars.Where(ch => ch != '0');
var allEqual = filtered.Count() == 0 || filtered.Distinct().Count() == 1;

这算是混乱和冗长吗

对我来说似乎没问题,前提是你只能拥有他们三个

return ((a == "0" || b == "0" || a == b) && (b =="0" || c =="0" || b == c) && (a =="0" || c =="0" || a == c));
优雅的解决方案 这需要对LINQ有基本的了解,并基于:

简单的解决方案 这是代码中逻辑的纯翻译,没有什么花哨的东西

static bool IsMatch(char x, char y)
{
    return x == y || x == '0' || y == '0';
}

static bool IsMatch(char a, char b, char c)
{
    return IsMatch(a, b) && IsMatch(b, c) && IsMatch(a, c);
}
第一个
IsMatch
重载在其参数相等或其中一个参数为
'0'
时返回
true
第二个重载只是为每对调用第一个重载

(请注意,由于通配符,我们无法使用transitive属性并仅比较两对。)

我不确定我会称之为优雅,但它并不可怕(甚至可能是正确的…)(注意,这或多或少是对Paddy上述答案的改进)。

您可以编写一个结构“MYChar”,实现
char
并覆盖
等于
、相等运算符和隐式转换,因此您可以:

MyChar a = 'a';
MyChar b = '0';

bool eq = a == b; //true
编辑 原来您无法从
char
继承,因为它是密封的,但我尝试了以下代码。它可以编译,但我不确定它是否有效。我从中编译了它,但当时我没有任何东西要测试

下面是:

public struct MyChar
{
    private static char _wild = '0';

    private char _theChar;

    public MyChar(char c)
    {
        _theChar = c;
    }

    public MyChar ()
        :this (_wild)
    {}

    private bool IsWildCard ()
    {
        return _theChar.Equals (_wild);
    }        

    public static implicit operator char (MyChar c)
    {
        return c._theChar;
    }

    public static implicit operator MyChar (char c)
    {
        return new MyChar (c);
    }


    public override bool Equals (object obj)
    {
        if (!(obj is MyChar))
        {
            return base.Equals (obj);
        }
        else
        {
            if (IsWildCard ())
            {
                return true;
            }
            else
            {
                MyChar theChar = (MyChar) obj;
                return theChar.IsWildCard () || base.Equals ((char) theChar);
            }
        }
    }

    public override int GetHashCode ()
    {
        return _theChar.GetHashCode ();
    }
}

对于任意数量的char值,都应该使用类似的方法:

public class Comparer
{
    public static bool AreEqualOrZero(params char[] values)
    {
        var firstNonZero = values.FirstOrDefault(x => x != '0');
        return values.All(x => x == firstNonZero || x == '0');
    }
}
通过以下单元测试:

[TestClass()]
public class ComparerTest
{

    [TestMethod()]
    public void Matches_With_Wildcard()
    {
        char[] values = {'0', '1', '1', '1'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_No_Wildcard()
    {
        char[] values = {'1', '1', '1', '1'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_Only_Wildcards()
    {
        char[] values = {'0', '0', '0'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_Zero_Length()
    {
        char[] values = {};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_One_Element()
    {
        char[] values = {'9'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_One_Wildcard_And_Nothing_Else()
    {
        char[] values = {'0'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Does_Not_Match_On_NonEqual_Sequence_No_Wildcard()
    {
        char[] values = {'1', '2', '1', '1'};
        Assert.IsFalse(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Does_Not_Match_On_NonEqual_Sequence_With_Wildcard()
    {
        char[] values = {'1', '2', '1', '0'};
        Assert.IsFalse(Comparer.AreEqualOrZero(values));
    }
}

如果将字符限制为ASCII而不是unicode,那么我喜欢: . (编辑回应评论指出我没有完全正确的规格,但我仍然喜欢基本的想法。添加了额外的测试作为验证)


对于包含无限个字符的更通用的解决方案,这就是正则表达式的作用:^()(\1 | 0)*$

这与公认的答案没有太大区别,但无论如何

var list = new List<Char> {'1', '1', '0'};

var check = list.Where(ch => ch != '0')
                .Distinct()
                .Count() < 2;
var list=新列表{'1','1','0'};
var check=list.Where(ch=>ch!=“0”)
.Distinct()
.Count()<2;
关于:

if ((a==b) && (b==c) && (a==c)) 
....
....


我的逻辑错了吗?

@BoltClock:逻辑是
a==b==c
,如果其中任何一个是
0
,那么它被认为是自动匹配的。“每个都可以是“0”,这意味着它匹配每个字符。”?@Yuck:你的意思是,如果其中任何一个是“0”,那么其他两个就根本不必匹配了吗?按照我的理解,假设
a='t'
b='t'
c=0
…这应该返回
true
,这意味着所有3个变量都“匹配”。对我来说,这看起来非常混乱和冗长。@Dan为什么第三次检查没有失败?@Arafinwe:在我发表评论时它不在那里:-)Paddy,最初我无法评论b/c我没有足够的代表性,因此我很抱歉直接编辑您的问题而不是仅仅评论,但编辑实际上是正确的-正如我在编辑中留下的评论所指出的,@Dan Abramov的假阳性为“4 0 5”(如果b==0,则无论其他变量的值如何,您的结果都是正确的…)你认为检查
chars会更容易吗?其中(c=>c!=“0”).Distinct().Count()我还认为,关于代码可读性,
chars.Count()==0
有点误导(因为
chars
已经过滤了通配符,但这表明我们正在检查原始字符)。还有,这类支票有
任何
。很好,我想现在看起来好多了。非常感谢。60年代的人打电话来,想要回他们的名单和
lambda
。“所有这一切以前都发生过,将来也会发生。”(我用一种略带讽刺但完全支持的方式表达这一评论。)非常好的解决方案,它是对原始问题的完美回答。但是,如果要对任意大小的数组/列表运行此操作,则使用
Distinct
并不是一种非常有效的表示
不存在的方式(用SQL来说)。假设您有一个包含一百万个元素的数组,其中第一个元素是1和2,您将遍历所有元素以获得
Distinct
的结果,因为我下面的回答将在第二个元素上返回false。请注意。您可能应该将其设置为
struct
(并且不要忘记实现
IEquatable
)。实际上,它必须是一个struct。我不会在这里实现IEquatable,但肯定这是一个好主意。是的,有必要避免持续的(非)拳击。这就是我,还是你在建造一艘飞行500米的宇宙飞船?@Erik:不太可能,他需要一个处理通配符的字符,我建造了一个处理通配符的字符。完成后,您可以向其添加任何通配符或任何需要的功能。<2可以是=!2但通过这种方式,您可以检查3个以上的项。从原始问题“如果a为'0',我只需要检查b==c”,因此这里的“通配符”概念并不表示立即匹配,而是应该忽略该字符。因此,除000和aaa之外的所有测试都应返回False,并且此解决方案无法捕获询问者的意图。@johnny:你说得对,更改了条件和测试。这使得它不太优雅,但仍比将其添加到列表中要好)。实际显示了预期的准确结果;从最初的问题:“如果a是‘0’,我只需要检查b==c”,例如,像a0a或bb0这样的东西应该是真的,而a0c或ab0应该是假的,所以提供的所有测试除了aa
public class Comparer
{
    public static bool AreEqualOrZero(params char[] values)
    {
        var firstNonZero = values.FirstOrDefault(x => x != '0');
        return values.All(x => x == firstNonZero || x == '0');
    }
}
[TestClass()]
public class ComparerTest
{

    [TestMethod()]
    public void Matches_With_Wildcard()
    {
        char[] values = {'0', '1', '1', '1'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_No_Wildcard()
    {
        char[] values = {'1', '1', '1', '1'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_Only_Wildcards()
    {
        char[] values = {'0', '0', '0'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_Zero_Length()
    {
        char[] values = {};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_One_Element()
    {
        char[] values = {'9'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Matches_With_One_Wildcard_And_Nothing_Else()
    {
        char[] values = {'0'};
        Assert.IsTrue(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Does_Not_Match_On_NonEqual_Sequence_No_Wildcard()
    {
        char[] values = {'1', '2', '1', '1'};
        Assert.IsFalse(Comparer.AreEqualOrZero(values));
    }

    [TestMethod()]
    public void Does_Not_Match_On_NonEqual_Sequence_With_Wildcard()
    {
        char[] values = {'1', '2', '1', '0'};
        Assert.IsFalse(Comparer.AreEqualOrZero(values));
    }
}
using System;
class example {
    static void elegant(char a, char b, char c) {
      int  y =  ((int) a - 48) + ((int) b - 48) + ((int) c - 48);
      int  z =  ((int) a - 48) * ((int) b - 48) * ((int) c - 48);

      bool result = y == ((int) a-48)*3 || (z ==0 && (a==b || b==c || a==c));
      Console.WriteLine(result);
    }
    static void Main() {

      elegant('0', 'b', 'c'); // false
      elegant('a', '0', 'c'); // false
      elegant('a', 'b', '0'); // false
      elegant('a', 'b', 'c'); // false
      elegant('0', '0', '0'); // true
      elegant('a', 'a', 'a'); // true
      elegant('0', 'a', 'a'); // true
      elegant('a', '0', 'a'); // true
      elegant('a', 'a', '0'); // true
      elegant('0', '0', 'a'); // true
      elegant('0', 'a', '0'); // true
      elegant('a', '0', '0'); // true
     }
}
var list = new List<Char> {'1', '1', '0'};

var check = list.Where(ch => ch != '0')
                .Distinct()
                .Count() < 2;
if ((a==b) && (b==c) && (a==c)) 
....
....