【问题标题】:How to write a character matching algorithm in JavaScript?如何在 JavaScript 中编写字符匹配算法?
【发布时间】:2017-05-12 02:06:20
【问题描述】:

鉴于此输入 s1 = "dadxx" s2 = "ddxx" 我希望输出包含一堆 a,b 对,只要 s1 中的每个字符与 s2 中的字符匹配,反之亦然(允许重复)。这些对中有0,0,因为s1[0]s2[0] 都等于d

问题是我的输出不包含2,1,即使s1[2]s2[1] 都等于d

有人可以修复我的算法或做出更好的算法吗?

Here's a JSFiddle 如果有帮助的话。

这是我的代码:

// For each char, see if other string contains it
s1 = 'dadxx'
s2 = 'ddxx'

matchChars(s1,s2)
matchChars(s2,s1)

function matchChars(a,b) {
    for (i = 0; i < a.length; i++) {
        found = b.indexOf(a[i])
        if (found >= 0) {
            if (a===s1) console.log(i,found)
            else console.log(found,i)
        }
    }
}

【问题讨论】:

  • 如果你把它们分成一个字符数组,我想array intersection 可能是你想要的?
  • @CrayonViolent 谢谢,但这更像是一个出色的数组交集,可以找到所有匹配项并返回它们的索引

标签: javascript algorithm


【解决方案1】:

我相信您遇到的问题是您使用indexOf 仅在s2 中检查s1[i] 的单个匹配项。这将找到匹配值的第一个索引,而不是每个索引。

如果您改为遍历两个字符串并比较每个字符,您会得到我认为您正在努力实现的结果。

// Define strings
s1 = 'dadxx'
s2 = 'ddxx'

matchChars(s1,s2)
matchChars(s2,s1)

function matchChars(a,b) {
  // Convert strings to lower case for case insensitive matching
  // Remove if case sensitive matching required
  a = a.toLowerCase();
  b = b.toLowerCase();

  // Iterate through every letter in s1
  for (i = 0; i < a.length; i++) {
    // Iterate through every letter in s2
    for (j = 0; j < b.length; j++) {
      // Check if the letter in s1 matches letter in s2
      if (a[i] === b[j]) {
        // Changed per request of OP
        (a === s1) ? console.log(i, j) : console.log(j, i);
        // console.log([i, j]);
      }
    }
  }
}

工作 JSBin 示例:https://jsbin.com/wecijopohi/edit?js,console

【讨论】:

  • 成功了。谢谢!!
  • 唯一的问题是有重复。
  • 嗯,你为什么要删除你最后的评论呢? (关于误报1,01,2
  • 我刚刚输出了与索引匹配的字母,字母是正确的。我只是再看一遍。 jsbin.com/wecijopohi/edit?js,console
  • 我在您的代码中看不到任何错误或重复。你只是用交换的参数调用了两次matchChars
【解决方案2】:

您说允许重复但不是必需的。我将此作为一种更现代的方法提交,而不是作为对已接受解决方案的更正,这对我来说看起来不错。 https://jsfiddle.net/avc705zr/3/

match = (a, b) => {
  let re, match, matches = []
  a.split('').forEach((l, i) => {
    re = new RegExp(l, 'g')
    while ((match = re.exec(b)) != null) {
      matches.push([i, match.index])
    }
  })
  return matches
}

但是,根据我的经验,当您真正需要这样的功能时,您只需要用尽其中一个字符串。换句话说,您正在寻找字符串 1 中所有实例的字符串 2 中的匹配项——也就是说,字符串 1 中的 unique 个字符。因此,现实世界中可能出现的修改可能而是像:

Array.prototype.unique = function() {
  return this.filter(function (value, index, self) { 
    return self.indexOf(value) === index;
  });
}

match = (a, b) => {
  let re, match, matches = []
  a.split('').unique().forEach(l => {
    re = new RegExp(l, 'g')
    while ((match = re.exec(b)) != null) {
      matches.push([l, match.index])
    }
  })
  return matches
}

【讨论】:

  • 谢谢!另一个优化(对于您的第一个答案)可能是仅在 unique pairs 上执行比较。
猜你喜欢
  • 2011-11-06
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多