嵌套数组的include()方法

时间:2019-02-05 23:25:19

标签: javascript arrays

我正在努力检查数组中的数组。似乎 const ReportRoute = (props) => { const [input, setInput] = useState(''); const testObject1 = { name: {input}, } return ( <div> <input value={input} onInput={e => setInput(e.target.value)} /> <Link to={{ pathname: `api/report/name`, search: queryString.stringify(testObject1), }} > Download {props.type} report </Link> </div> ); }; 方法不是为此设计的,因为在这种情况下它总是返回include()。以下是与false相同的场景的示例。也许我需要的只是语法帮助,欢迎任何想法。

indexOf

当然,以上返回arr = [1,[9,9],3,4,5]; if (arr.indexOf(el) !== -1) { console.log(`the array contains ${el}`); } else { console.log(`doesn't contain ${el}`); } 代表1、3、4、5,true代表2。现在是问题所在。我正在尝试使用类似false的数组来填充此方法,以查看是否已经存在。

[9,9]

另一方面,以下内容还可以,这使我认为这只是语法问题(?)

let el = [9,9];
// console: "doesn't contain 9,9"

我通过编写带有let el = arr[1]; // console: "the array contains 9,9" 循环的检查器函数找到了解决该问题的方法,但是随着您添加需求,这很快变得很庞大。我想知道一种更聪明的方法。

谢谢。

3 个答案:

答案 0 :(得分:3)

您遇到的问题是数组是引用类型。因此,仅当两个数组引用相同的基础数组时,比较两个数组才返回true;对于不同的数组,即使它们具有相同的值,也将返回false。

const arr1 = [1, 2];
const arr2 = [1, 2];
const arr3 = arr1;

console.log(arr1 === arr3);
console.log(arr1 !== arr2);

要解决您的问题,您的include函数需要按值比较(深度比较),只需使用JSON.stringify()即可做到这一点。

  

此方法快速但有局限性,当您具有简单的JSON样式对象而内部没有方法和DOM节点时,此方法就可以使用

有关JavaScript中的对象比较,请参见此SO post

这是一个有效的示例:

function include(arr, value) {
  const stringifiedValue = JSON.stringify(value);
  for (const val of arr) {
    if (JSON.stringify(val) === stringifiedValue) {
      return true;
    }
  }
  return false;
}

console.log(include([1, 2, 3, 4], 3));
console.log(include([1, 2, 3, [1, 2]], [1, 2]));
console.log(include([1, 2, 3, [1, 2]], [1, 2, 3]));

这是另一种方式,无需JSON.stringify()即可进行此深度比较,它适用于内部数组和标量值:

function include(arr, value) {
  const valArity = Array.isArray(value) ? value.length : 1;
  for (let item of arr) {
    if (valArity > 1 && Array.isArray(item) && item.length === valArity) {
      if (item.every((val, i) => val === value[i])) {
        return true;
      }
    } else if (item === value) {
      return true;
    }
  }
  return false;
}

console.log(include([1, 2, 3, 4], 3));
console.log(include([1, 2, 3, [1, 2]], [1, 2]));
console.log(include([1, 2, 3, [1, 2]], [1, 2, 3]));
console.log(include([1, 2, 'abc', 4], 'abc'));

这是经过修改的版本,适用于具有标量属性,数组和标量的简单对象

function include(arr, value) {
  const valArity = Array.isArray(value) ? value.length : 1;
  const isObject = value instanceof Object;
  for (let item of arr) {
    if (valArity > 1 && Array.isArray(item) && item.length === valArity) {
      if (item.every((val, i) => val === value[i])) {
        return true;
      }
    } else if (isObject && item instanceof Object && item) {
      const numEntries = Object.keys(value).length;
      const entries = Object.entries(item);
      if (numEntries === entries.length) {
        if (entries.every(([k, v]) => value[k] === v)) {
          return true;
        }
      }
    } else if (item === value) {
      return true;
    }
  }
  return false;
}

console.log(include([1, 2, 3, 4], 3));
console.log(include([1, 2, 3, [1, 2]], [1, 2]));
console.log(include([1, 2, 3, [1, 2]], [1, 2, 3]));
console.log(include([1, 2, { a: 1 }, 4], { a: 1 }));
console.log(include([1, 2, { a: 1, b: 2 }, 4], { a: 1 }));
console.log(include([1, 2, 'abc', 4], 'abc'));

答案 1 :(得分:1)

在这里,我们可以使用Array.prototype.some()

注意,我们添加了一个辅助方法来检查每个元素,我没有费心编写对象检查,但是您明白了。

经过调整以支持子数组

let arr = [1, [9, 9], 3, 4, 5];
let el = [9, 9];

let arr2 = [1, [1,[9, 9]], 3, 4, 5];
let el2 = [1,[9, 9]];

const someCheck = (item, compare) => {
  if(typeof item !== typeof compare) return false;
  if(typeof item === 'string') return item === compare;
  if(typeof item === 'number') return item === compare;
  if(Array.isArray(item)) {
    console.log('checking array');
    return item.reduce((accum, o, i) => accum && (someCheck(o,compare[i])));
  }
  // no plain object support yet.
  return false;
}


if (arr.some(e => someCheck(e, el))) {
  console.log(`the array contains ${el}`);
} else {
  console.log(`doesn't contain ${el}`);
}

if (arr2.some(e => someCheck(e, el2))) {
  console.log(`the array contains ${el2}`);
} else {
  console.log(`doesn't contain ${el2}`);
}

答案 2 :(得分:-1)

您需要遍历数组并检查每个元素是否为数组,然后检查每个索引。像这样:

let arr = [1,[9,9],3,4,5];
let el = [9,9];
let contains = true;

for (var i = 0; i < arr.length; i++) {
  if (Array.isArray(arr[i])) {
    var equals = true
    if(arr[i].length !== el.length)
        equals = false;
    for(var j = arr[i].length; j--;) {
        if(arr[i][j] !== el[j])
           equals = false;
    }  
    if (equals) {    
      contains = true;
      break;
    }
  } else {
    if (arr.indexOf(el) !== -1){
        contains = true;        
        break;
      }
    else{contains = false;}
  }
}

if (contains) {
  console.log(`the array contains ${el}`);
} else {
  console.log(`doesn't contain ${el}`)
}