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

col*_*ang 17 c# puzzle equality

假设我有3个char变量a,bc.
每一个都可以'0',这是一个特例,意味着它匹配每个字符.

所以,如果是'0',我只需要检查是否b == c.
我想检查是否a == b == c,但发现C#中的实现变得混乱和冗长.

您可以提供任何创意或漂亮的解决方案吗?

更新

对于绩效驱动,采取Erik A. Brandstadmoen的方法.为简单起见,使用M4N的apprach,我也做了一些修改:!(query.Any() && query.Distinct().Skip(1).Any())

M4N*_*M4N 35

像这样的东西:

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;
Run Code Online (Sandbox Code Playgroud)

解释解决方案:

  • 首先将所有字符放入列表中
  • 排除所有'0'的字符: .Where(ch => ch != '0')
  • 所有剩余的字符都相等,如果:
    • 其余的集合不包含任何元素: chars.Count() == 0
    • 或唯一剩余元素的数量是1: chars.Distinct().Count() == 1

更新:这是一个不同的版本,它不使用LINQ但仍然可读(IMO).它作为一种方法实现,可以使用任意数量的字符进行调用:

public bool AllEqualOrZero(params char[] chars)
{
    if (chars.Length <= 1) return true;
    char? firstNonZero = null;
    foreach (var c in chars)
    {
        if (c != '0')
        {
            firstNonZero = firstNonZero ?? c;
            if (c != firstNonZero) return false;
        }
    }
}

// Usage:
AllEqualOrZero('0', '0', '0'); // -> true
AllEqualOrZero('0', '1', '1'); // -> true
AllEqualOrZero('2', '1', '0'); // -> false
AllEqualOrZero();              // -> true
AllEqualOrZero('1');           // -> true
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,这段代码给出了'0 0 0`的假阴性. (7认同)
  • 这很漂亮. (3认同)
  • 60年代正在呼唤并希望他们的名单和`lambda`回来."所有这一切都发生过,并将再次发生." (我用一种略带反讽但完全支持的方式表达了这一评论.) (3认同)

Dan*_*mov 18

优雅的解决方案

这需要对LINQ有基本的了解,并且基于M4N解决方案:

static bool IsMatch(params char[] chars)
{
    return chars.Where(c => c != '0')
                .Distinct().Count() <= 1;    
}
Run Code Online (Sandbox Code Playgroud)

编辑

本来我的解决方案从M4N的解决方案不同,但一些简化后,我来到东西(几乎)一模一样.虽然积分完全归功于他,但我会留下它作为参考.

true当集合中最多有一个不同的非通配符时,它返回.
我让它接受了可变数量的参数,因此您可以将其称为2个,3个或更多个字符:

bool match = IsMatch('3', '3', '4', '0');
Run Code Online (Sandbox Code Playgroud)

简单的解决方案

这是您的代码中逻辑的纯粹翻译,没有花哨的东西.

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);
}
Run Code Online (Sandbox Code Playgroud)

当参数相等或其中之一IsMatch为时true,第一个重载返回'0'.
第二个重载只是为每对调用第一个.

(请注意,由于通配符,我们无法使用传递属性并只比较两对.)


Eri*_*oen 2

像这样的东西应该适用于任意数量的 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');
    }
}
Run Code Online (Sandbox Code Playgroud)

通过以下单元测试:

[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));
    }
}
Run Code Online (Sandbox Code Playgroud)