有没有更好的方法检查数组中的相似性?

时间:2019-05-09 15:41:23

标签: javascript ecmascript-6

我收到一个返回的响应和一系列哈希。散列数组具有两个键“ title”和“ paragraph”。有时我会收到在段落键中返回相似值的响应。

例如,当我只返回段落中的值时:

["Welcome to the best place", "Welcome to the best place in the world, Boston!"]

您看到索引0包含索引1的内容

我正在遍历哈希数组以返回键之一“ paragraph”。然后,如果值等于数组中的任何其他元素,则尝试过滤出第一个元素。我只有在数组具有与上面的状态相似的值时才起作用,并且如果失败则将返回一个空数组。

const description = hotel
    .description()
    .map(descriptions => descriptions.paragraph)
    .filter((paragraph, index) => !paragraph[index].includes(paragraph[0]))

hotel.description()返回哈希数组,要过滤的地图链将结果返回数组

上面的示例代码返回有效的响应,其中数组:

["Welcome to the best place", "Welcome to the best place in the world, Boston!"]

成为:

["Welcome to the best place in the world, Boston!"]

但是,如果返回的数组是唯一的,则会返回一个空数组。

预期结果是:

["You are here at the best place", "Welcome to the best place in the world, Boston!"]

实际结果是: []

不确定要在此链上附加什么,以使其返回唯一值。

3 个答案:

答案 0 :(得分:2)

我正在简化您的示例以使用它,但是该概念在这里仍然适用。我还在做以下假设:

  • “相似”是指“包含”
  • 您将对所有相似之处感兴趣,而不仅仅是与第一个相似之处
  • 您的原始数据没有严格的重复短语(不过可以解决此问题)
  • 您宁愿删除子集短语并保留超集短语(如果这是合理的话)。

如果是这样,那么以下方法似乎可以满足您的需求:

let greetings = [
  "Welcome to the best place", 
  "Welcome to the best place in the world, Boston!"
];

let condensed = 
  greetings
  .filter(g => 
    !greetings.some(other => other.includes(g) && !(other == g))
  );

console.log(condensed);

在这里,当所有值都不相似时,它不会返回空数组:

let greetings = [
  "You're at the best place", 
  "Welcome to the best place in the world, Boston!"
];

let condensed = 
  greetings
  .filter(g => 
    !greetings.some(other => other.includes(g) && !(other == g))
  );

console.log(condensed);

答案 1 :(得分:1)

这是一种可能性。我从保持相似项的逻辑中分离出相似性的检测和选择两个相似项中的更好者。函数includes仅报告两个字符串中的一个是否为另一个字符串的子字符串,而longer选择两个字符串中的较长者。

显然,这些辅助功能可以嵌入到主功能中,但是我认为这更合乎逻辑。

const keepSimilar = (similarTo, better) => (xs) => 
  xs.reduce((found, x) => {
    const index = found.findIndex(similarTo(x))
    if (index > -1) {
      found[index] = better(x, found[index])
    } else {
      found.push(x)
    }
    return found
  }, [], xs)

const includes = (s1) => (s2) => s1.includes(s2) || s2.includes(s1)
const longer = (s1, s2) => s2.length > s1.length ? s2 : s1 

const similarParas = keepSimilar(includes, longer)

const paras = ['foo', 'bar', 'baz', 'foobar', 'bazqux']

console.log(similarParas(paras)) //=> ['foobar', 'baz', 'barqux']
console.log(similarParas(['ABC', 'AB', 'DEF', 'DEFG'])) //=> ['ABC','DEFG']
console.log(similarParas([
  'Welcome to the best place', 
  'Welcome to the best place in the world, Boston!'
]))
//=> ['Welcome to the best place in the world, Boston!']

console.log(similarParas([
  'You are here at the best place', 
  'Welcome to the best place in the world, Boston!'
]))
//=> ['You are here at the best place', 'Welcome to the best place in the world, Boston!']

这不是很漂亮的代码。我是Ramda的原则之一,对于这样的库,我会做得非常不同,尤其要避免累加器对象的突变。但这应该可行。

答案 2 :(得分:0)

以下是使用reduce数组理解来一次完成操作的方法:

Private Sub Application_Startup()
     Call Initialize_handler
End Sub