【问题标题】:How could I improve and shorten the following algorithm which compares two arrays and returns the symmetric discrepancies in between them?如何改进和缩短以下比较两个数组并返回它们之间的对称差异的算法?
【发布时间】:2019-11-02 16:53:57
【问题描述】:

我创建了这个函数,在这个社区的一些帮助下,我想知道我的 if 语句是否可以缩短或改进,因为我还是 JS 的新手,改进这个函数可以让我接触到新的知识。

请看下面的代码:

let jo = [1,2,3,5,6]
let ji = [1,2,3,5,4]

const checker = (arr1, arr2) => {
   
    return arr1.every(num => arr2.includes(num)) == false && 
    arr2.every(num => arr1.includes(num)) == false ? 
    Array.from(new Set(arr1.filter(x => !new Set(arr2).has(x))))
    .concat(Array.from(new Set(arr2.filter(x => !new Set(arr1).has(x))))) :
    arr1.every(num => arr2.includes(num)) == false? 
    Array.from(new Set(arr1.filter(x => !new Set(arr2).has(x)))) :
     arr2.every(num => arr1.includes(num)) == false ?
     Array.from(new Set(arr2.filter(x => !new Set(arr1).has(x)))) :
     "no discrepancies"
}

console.log(checker(jo, ji));

【问题讨论】:

  • let difference = arrA .filter(x => !arrB.includes(x)) .concat(arrB.filter(x => !arrA.includes(x)));
  • @Prune 虽然这可能是未来关于 CR 的话题,但请不要以 CR 站点的存在作为关闭问题的理由。评估请求并使用太宽泛主要基于意见等原因。然后您可以向 OP 提及它可以在 Code Review 上发布(如果是) on-topic。请参阅this answer to A guide to Code Review for Stack Overflow users 中的你不应该做的事情部分
  • @SᴀᴍOnᴇᴌᴀ:谢谢!我已经有一年多没有阅读 CR 标准了。很抱歉,感谢您的更新。

标签: javascript arrays algorithm


【解决方案1】:

由于您实际操作的是集合而不是数组,因此最好明确使用Set 对象。首先,让我们定义几个原语:

// A U B
let union = (a, b) => new Set([...a, ...b]);

// A \ B
let complement = (a, b) => new Set([...a].filter(x => !b.has(x)));

那么,对称差分运算可以很简单

// A d B = (A \ B) U (B \ A)
let difference = (a, b) => union(complement(a, b), complement(b, a))

如果您需要check 函数来接受和返回数组,您可以这样定义:

let check = (a, b) => [...difference(new Set(a), new Set(b))]

FWIW,这是一个带有基本集合操作的小型“库”:

const
    _set = x => x instanceof Set ? x : set.from(x),
    _has = s => Set.prototype.has.bind(_set(s)),
    _array = x => Array.isArray(x) ? x : [...x],
    _not = f => x => !f(x),
    _empty = s => s.size === 0,
    _everyfn = fns => x => fns.every(f => f(x));

const set = {};

set.from = x => new Set(x);
set.of = (...args) => set.from(args);

set.union = (...args) => set.from(args.map(_array).flat());
set.intersection = (a, ...rest) => set.from(_array(a).filter(_everyfn(rest.map(_has))));
set.complement = (a, b) => set.from(_array(a).filter(_not(_has(b))));
set.difference = (a, b) => set.union(set.complement(a, b), set.complement(b, a));
set.includes = (a, b) => _empty(set.complement(b, a));

// examples:

console.log(...set.union('abc', 'abxy', 'abz'))
console.log(...set.intersection('abc', 'abxy', 'abz'))
console.log(...set.complement('abcd', 'abxy'))
console.log(...set.difference('abcd', 'abxy'))
console.log(set.includes('abcd', 'ac'))
console.log(set.includes('abcd', 'ax'))

【讨论】:

  • 这是O(n)吗?
  • @marzelin unionO(m+n) 因为它需要经过两组大小mncomplementO(n) 因为b 是一个带有O(1) 查找的Set,所以你只需要关心a 的大小。 difference 执行 O(n) 操作和 O(m) 操作(complement 两次)并将其输入到 O(m+n) 操作中。这再次简化了(如果我没记错的话)O(m+n)。最后,check 是对O(m+n) 操作(difference)结果的O(n) 操作(传播)。这应该仍然是O(m+n)。我们可以进一步简化并将其称为O(n),因为这一切都是线性的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
相关资源
最近更新 更多