查找两个数组之间的匹配序列(模式匹配)C#

时间:2020-02-15 17:39:40

标签: c# arrays

我有两个数组,一个是我要比较的主数组,第二个数组有许多整数,它们的顺序可能向右或向左移动,并且还可能包含默认值。

此比较的结果(对/错)如下:

x = -9; //unknown number

int[] mainArray = new int[]{3,1,0,1};

int[] a = new int[]{x,x,x,x}; // true
int[] b = new int[]{x,x,1,x}; // true
int[] c = new int[]{x,x,1,0}; // true
int[] d = new int[]{x,x,1,0}; // true
int[] e = new int[]{x,3,1,0}; // true
int[] f = new int[]{1,3,1,0}; // true
int[] g = new int[]{3,1,0,x}; // true
int[] h = new int[]{3,1,1,0}; // false
int[] i = new int[]{x,1,1,x}; // false
int[] j = new int[]{0,1,1,x}; // false
int[] k = new int[]{3,1,x,x}; // true

搜索序列是否存在于主数组中的方法是什么? 我无法解决两个问题: 1)数组可能会向右或向左移动,但是即使将其移动,结果也为true 2)比较中跳过的x值

我最终做了很多if语句,但是我确信这个问题已经被其他人很好地解决了。

2 个答案:

答案 0 :(得分:1)

想法:将输入转换为字符串并将其复制,以使其包含移位的变体:

{ 3, 1, 0, 1 } ==> ",3,1,0,1,3,1,0,1,"

将模式数组转换为正则表达式。每个x\d+替换,表示一个或多个数字:

{ 3, 1, x, x } ==> ",3,1,\d+,\d+,"

然后比较。

string inputAsString = String.Join(",", mainArray) + ",";
inputAsString = "," + inputAsString + inputAsString;

string pattern =
    "," + String.Join(",", input.Select(i => i == x ? @"\d+" : i.ToString())) + ",";

bool result = Regex.IsMatch(inputAsString, pattern);

input是数组ak之一。


这里是一个版本,它告诉您阵列移位了多少。为此,我们将数字格式化,以使它们都具有相同的长度。这使我们能够从输入字符串中匹配位置的位置计算出偏移量。

const int x = -9; //unknown number

int[] mainArray = new int[] { 3, 1, 0, 1 };

int[][] inputs = new[]{ //        is match, shift
        new int[] { x, x, x, x }, // true    0
        new int[] { x, x, 1, x }, // true    1
        new int[] { x, x, 1, 0 }, // true    1
        new int[] { x, x, 1, 0 }, // true    1
        new int[] { x, 3, 1, 0 }, // true    1
        new int[] { 1, 3, 1, 0 }, // true    1
        new int[] { 3, 1, 0, x }, // true    0
        new int[] { 3, 1, 1, 0 }, // false
        new int[] { x, 1, 1, x }, // false
        new int[] { 0, 1, 1, x }, // false
        new int[] { 3, 1, x, x },  // true   1           
        //-------- all possible shifts:
        new int[] { 3, 1, 0, 1 },  // true   0 <=> -4          
        new int[] { 1, 3, 1, 0 },  // true   1 <=> -3          
        new int[] { 0, 1, 3, 1 },  // true   2 <=> -2          
        new int[] { 1, 0, 1, 3 },  // true   3 <=> -1            
};

const int digits = 3;
string format = new String('0', digits);
string inputAsString =
    String.Join(",", mainArray.Select(i => i.ToString(format))) + ",";
inputAsString = "," + inputAsString + inputAsString;
Console.WriteLine($"inputAsString = \"{inputAsString}\"");
foreach (int[] input in inputs) {
    string pattern =
        "," + String.Join(",", input.Select(i => i == x ? @"\d+" : i.ToString(format))) + ",";

    var match = Regex.Match(inputAsString, pattern);
    int shift = -match.Index / (digits + 1);
    if (shift <= -input.Length / 2) {
        shift += input.Length;
    }
    Console.WriteLine($"match = \"{match.Value}\", success = {match.Success}, index = {match.Index}, shift = {shift}");
}

此版本还将一些测试输出写入控制台。

答案 1 :(得分:1)

如果我正确地获得了问题说明,则可以尝试执行以下操作:

class MyEqualityComparer : IEqualityComparer<int>
{
    private int specialValue;
    public MyEqualityComparer(int specialValue) {this.specialValue = specialValue;}

    public bool Equals(int x, int y)
    {
        if (y == specialValue) return true;
        return x.Equals(y);
    }

    public int GetHashCode(int obj)
    {
        return obj.GetHashCode();
    }
}
void Main()
{
    int x = -9; //unknown number

    int[] mainArray = new int[] { 3, 1, 0, 1 };

    var lists = new List<int[]> {
    new int[] { x, x, x, x }, // true
    new int[] { x, x, 1, x }, // true
    new int[] { x, x, 1, 0 }, // true
    new int[] { x, x, 1, 0 }, // true
    new int[] { x, 3, 1, 0 }, // true
    new int[] { 1, 3, 1, 0 }, // true
    new int[] { 3, 1, 0, x }, // true
    new int[] { 3, 1, 1, 0 }, // false
    new int[] { x, 1, 1, x }, // false
    new int[] { 0, 1, 1, x }, // false
    new int[] { 3, 1, x, x }, // true
    };
    var mainRepeated = mainArray.ToList();
    mainRepeated.AddRange(mainArray);
    foreach (var e in lists)
    {
        foreach (var i in Enumerable.Range(0, mainArray.Length))
        {
            if (mainRepeated.Skip(i).Take(e.Count()).SequenceEqual(e, new MyEqualityComparer(x)))
            {
                Console.WriteLine(e.Aggregate(new StringBuilder(), (sb,s) => (s==x? sb.Append("x") : sb.Append(s)).Append(",")).ToString()); // we've got a match
                break;
            }
        }
    }
}