如何在Javascript中比较一个字符串数组?

7
我想检查两个字符串数组是否相等。
例如: compare(["abc", "def"], ["def", "abc"]) 应该返回true,同样地,
compare(["abc", "def"], ["def", "ghi"]) 

应该返回false

最佳的做法是什么?


请提供您正在尝试的代码。 - unicorn2
1
可以对数组进行排序并比较a[n]和b[n],或者跳过排序并在b的每个位置查找a[n]。 - Culme
2
可能是如何在JavaScript中比较数组?的重复问题。 - Ashish Rajput
7个回答

5

JavaScript没有Set或Multiset数据结构(至少,没有一个被广泛支持的),这是你通常用于测试两组项目是否相同而不考虑顺序的数据结构。因此,我建议对数组进行排序并检查它们的内容是否相等。如果您知道数组只包含字符串,则可以使用简单的相等性来检查项目:

function compare(array1, array2) {
  if (array1.length != array2.length) {
    return false;
  }

  array1 = array1.slice();
  array1.sort();
  array2 = array2.slice();
  array2.sort();

  for (var i = 0; i < array1.length; i++) {
    if (array1[i] != array2[i]) {
      return false;
    }
  }

  return true;
}

console.log(compare(["abc", "def"], ["def", "abc"])); // true
console.log(compare(["abc", "def"], ["def", "ghi"])); // false

对于更一般的情况,你需要一个更复杂的相等定义,我建议浏览这个问题的答案。


我认为你在 if (array1[i] != array2[i]) { return false; } 的逻辑上有问题。如果没有找到匹配项,你不应该中断程序,而是应该继续寻找匹配项。 - Royi Namir
看起来它们必须被视为相等,如果它们包含相同的项目,即使顺序不同。这不会通过您的检查。这将是一个n^2的迭代...或者需要排序,就像您实现的那样。 - Davide Rossi
谢谢您的回答。这是最有效的方法吗?JS没有任何内置函数来执行此操作吗? - Abhijith S
我认为我已经解决了你的评论。我最初误读了问题,并期望数组完全相等。现在我采用与 Culme 相同的方法对数组进行排序。 - alltom
Abhijith:我通常使用这种方法。在极端情况下,我会将array1中的所有项作为键放入一个对象中(JavaScript最接近Set数据结构的东西),以便在迭代array2时获得恒定时间查找,但我几乎从未需要过。 - alltom

5
JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

非常适用于基本类型,但要注意许多陷阱。https://masteringjs.io/tutorials/fundamentals/compare-arrays - Papasmile

3

朴素算法:O(N^2)

function compare(array1, array2){
  for (var i = 0; i < array1.length; i++){
    if (array2.indexOf(array1[i]) < 0) return false;
  }
  return true;  
}

更好的方法:(使用排序,O(NLOGN))
function compare(array1, array2){
  array1.sort();
  array2.sort();
  for (var i = 0; i < array1.length; i++){
    if (array1[i] !== array2[i]) return false;
  }
  return true;  
}

3
这两个需要在开头加上 if(array1.length !== array2.length) { return false } 才能正常工作。 - Ethan

1

我建议遵循ES6-oneliner

const compare = (a1, a2) =>
  (a1 = new Set(a1)) &&
  (a2 = new Set(a2)) &&
  a1.size === a2.size &&
  [...a1].every(v => a2.has(v));
  1. 通过将数组转换为集合来删除重复项(对于 compare(['a', 'a'], ['a', 'b']) 应返回 false)。
  2. 长度比较(对于 compare(['a', 'b'], ['a', 'b', 'c']) 应返回 false)。
  3. 检查第一个集合中的项目是否存在于第二个集合中。

这将对 a1 = ['foo', 'foo']a2 = ['foo', 'bar'] 返回 true。 - Stephen Harris
@StephenHarris 谢谢!我使用了 Set 转换来解决重复的情况。 - dhilt

0

统一解决方案:

function compare(a, b){
      var isEqual = false;  
      if (Array.isArray(a) && Array.isArray(b) && a.length == b.length){
          a.sort();
          b.sort();
          var i;
          for (i = 0; i < arr1.length; i++){
              if (a[i] === b[i]){
                  isEqual = true;
              } else{
                  isEqual = false;
                  break;
              }
          }

      }
      return isEqual;
}

var arr1 = ["def", "abc"], arr2 = ["abc", "def"];
console.log(compare(arr2,arr1)); // gives 'true'

console.log(compare(["abc", "def"], ["def", "ghi"])); // gives 'false'

https://jsfiddle.net/ob7e5ye5/4/


0
function compare(arr1, arr2){
    var match = true
    if(arr1.length != arr2.length){
        match = false
    }
    arr1 = arr1.slice();
    arr1.sort();
    arr2.slice();
    arr2.sort();
    for(var i = 0; i < arr1.length; i++){
        if(arr1[i] != arr2[i]){
            match = false;
        }
    }
    return match;
}

console.log(compare(["abc", "def"], ["def", "abc"])); // it will return true
console.log(compare(["abc", "def"], ["def", "ghi"])); // it will return false

0

有序或无序的冗长 TypeScript 示例
(显然受到 @dhilts 上面的回答 的启发)

const VERBOSE = console.log // ()=>void

const areDeduplicatedArraysEqualUnordered = (a1: any[] | Set<any>, a2: any[] | Set<any>) => {
    (a1 = new Set(a1)); (a2 = (new Set(a2))); VERBOSE('checking arrays as Sets', { a1, a2 })
    return !!(a1.size === a2.size && [...a1].every(v => (a2 as Set<any>).has(v)))
}
const areDeduplicatedArraysEqualOrdered = (a1: any[], a2: any[]) => {
    (a1 = [...(new Set(a1))] as any[]) && (a2 = [...(new Set(a2))] as any[]) && VERBOSE('checking deduplicated arrays', { a1, a2 })
    return !!(a1.length === a2.length && a1.every((v: any, i) => a2[i] === v))
}

const a2 = [3,5,8]
const a1 = [8,5,3]
const notEqual = areDeduplicatedArraysEqualOrdered(a1,a2)
const yesEqual = areDeduplicatedArraysEqualUnordered(a1,a2)
VERBOSE('results', { notEqual, yesEqual})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接