【问题标题】:How to find existence of an array in a set?如何在集合中找到数组的存在?
【发布时间】:2019-08-16 04:31:09
【问题描述】:

既然 Javascript 中的 set 能够获取对象,包括数组,我如何找到一个 set 中的数组列表的存在?

我尝试了以下代码:

var sello = new Set();
sello.add(["a","b"])
console.log(sello.has(["a","b"])) // outputs false

我假设

sello.has(["a","b"])

应该输出为真,因为我已经在集合sello 中添加了确切的数组。我是否遗漏了一些虚假的事实或任何逻辑错误?

注意:

  • 我不想只匹配字符 "a" 和/或 "b",我是 寻找匹配整个数组["a","b"]

  • 我正在寻找匹配数组。我只需要内容是
    相同,元素不必是相同的顺序。

【问题讨论】:

  • @imjared 正在比较 2 组,我希望在一组中找到一些东西。可以在集合中插入更多数组。我只是没有写出来。觉得没必要。

标签: javascript set


【解决方案1】:

您尝试执行的操作不起作用,因为在 Javascript 中您无法比较这样的数组,即使它们具有相同的值。这是因为数组是引用类型,而不是值类型,对于引用类型,Javascript 根据它们是否引用相同的对象(即内存中的相同位置)来确定它们是否相等。例如,只需尝试:

console.log(['a','b'] == ['a','b']); // false

尽管具有相同的值,但每个数组都是一个新的引用,因此它们彼此不相等。

相比之下,下面代码中的比较确实涉及到等式两边引用同一对象的数组:

let a = ['a','b'];
console.log(a == a); // true

因此:

let sello = new Set();
sello.add(a);
console.log(sello.has(a)); // true

为了解决这个问题,您需要创建一个函数来根据数组的值比较数组。您可以首先检查数组是否具有相同的长度。如果不是,那么它们就不相等。然后,您可以遍历每个项目中的项目,看看任何给定位置是否有任何不同。如果是这样,它们就不相等了。否则,假设您正在处理原始值的平面数组(没有引用类型的嵌套对象),那么数组是相等的。这就是我在下面的“isEqual”中所做的:

function isEqual(x,y) {
    if (x.length != y.length)
        return false;
    for (let i in x)
        if (x[i] != y[i])
            return false;
    return true;
}

如果你愿意,可以测试一下:

console.log(isEqual(['a','b'],['a','b'])); // true

现在,很遗憾,Set.has() 不接受函数,所以我们不能将它与 isEqual 一起使用。但是你可以循环遍历集合的值。如果创建单线是目标,那么我发现的最佳方法是将集合转换为数组并使用some 方法。 some 接受一个计算每一行的函数,如果它对任何一行返回 true,则结果为 true,否则为 false。

console.log(
    [...sello].some(item => isEqual(item, ['a','b']))
); 
// true

【讨论】:

  • 我添加了一个编辑以加粗该行,这有助于我理解并消除我的困惑。我希望你不要介意。 =) 谢谢!
  • @ccsalison,继续并再次尝试编辑,据我所知,他似乎没有通过。
【解决方案2】:

在 JavaScript 中,数组是对象,没有两个单独的对象被认为是相等的。

MDN 显示与标准对象相同的错误:

var set1 = new Set();
var obj1 = {'key1': 1};
set1.add(obj1);

set1.has(obj1);        // returns true
set1.has({'key1': 1}); // returns false because they are different object references


.has 与对象(例如数组)一起使用的最简单方法是获取对象的引用,例如:

let sello = new Set();
let myArray = ["a","b"];
sello.add(myArray);

console.log(sello.has(myArray)); // outputs true


如果您无法获得对数组的引用,您可能需要通过遍历数组并单独比较每个元素来检查 Set 中的每个数组。

你可以更简洁地做到这一点,但这个明确的例子阐明了这个过程:

// Declares and populates the Set
let sello = new Set();
sello.add( ["a", "c"] );
sello.add( ["a", "b"] );
sello.add( ["b", "c"] );

// Tests the `setHasArray` function
let result = setHasArray(sello, ["a", "b"]);
console.log(`result: ${result}`);

// Defines the `setHasArray` function
function setHasArray(theSet, arrayToMatch){

  // Creates a flag
  let isMatch = false;

  // Iterates through the Set
  for (let member of theSet){

    // Logs the Array we're about to compare elements of
    console.log("comparing:", member);

    // Makes sure this member is an Array before proceeding
    if(Array.isArray(member)){

      // Tentatively sets the flag to `true`
      isMatch = true;

      // Iterates through the Array, comparing each value
      arrayToMatch.forEach( (_, index) => {

        // Logs the comparison for the current value
        console.log(
          member[index]
          + (member[index] === arrayToMatch[index] ? " === " : " !== ")
          + arrayToMatch[index]
        );

        // Even one non-matching element means the Array doesn't match
        if(member[index] !== arrayToMatch[index]){
          console.log("Rats! Looked like a possible match there for a second.");
          isMatch = false;
        }
      });

      // Logs a successful match for the current member of the Set
      if(isMatch){
        console.log("Found a match!")

        // Stops checking Arrays lest the flag get reset and give us a false negative
        break;
      }
    }
  }

  // Returns our result
  return isMatch;
}

(如果您不熟悉此方法,请参阅.forEach on MDN。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多