【问题标题】:Is there a better way to check for similarities within an array?有没有更好的方法来检查数组中的相似性?
【发布时间】:2019-05-09 15:41:23
【问题描述】:

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

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

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

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

我正在映射哈希数组以返回其中一个键“段落”。然后,如果该值等于数组中的任何其他元素,我会尝试过滤掉第一个元素。我有一些东西只有在数组具有与上述状态相似的值时才有效,如果失败将返回一个空数组。

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!"]

实际结果是: []

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

【问题讨论】:

  • 你想得到所有在标题和段落中常见的词吗?
  • @MurtazaHussain 如果所有值都是唯一的,我想返回段落的数组,并过滤​​掉长度相似的值。
  • 我不得不多想一下如何实现你想要的,但我认为你的代码失败的原因是 paragraph[index]paragraph[0] 是你当前段落中的字符,不是段落列表中的条目。
  • 所以对于 [ABC, AB, DEF, DEFG] 你期待 [ABC, DEFG]?同样使用段落 [0] 确实没有什么意义。
  • @user1514042 没错。

标签: javascript ecmascript-6


【解决方案1】:

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

  • “类似”表示“包括”
  • 您会对所有相似之处感兴趣,而不仅仅是与第一个相似之处
  • 您的原始数据没有严格的重复短语(虽然这可以解决)
  • 您更愿意删除子集短语并保留超集短语(如果这样做有意义的话)。

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

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);

【讨论】:

  • 针对一些用例进行了测试,效果非常好。谢谢。
  • 太棒了!在您发表评论后,我对答案进行了简单的编辑。将“startswith”更改为“includes”。在这种情况下没有更改输出,我认为它更好地满足您的需求,因为这是您在问题中所做的。如果你觉得值得,别忘了接受这个答案。
  • 关于严格重复,“!(其他== g)”表达式防止数组变为空。然而,它也使得所有严格重复的实例都将输出到结果中。因此,您必须事先清理您的阵列或之后清理结果以消除重复项。请参阅here 了解如何执行此操作。
【解决方案2】:

这是一种可能性。我将相似性的检测和选择两个相似项目中的更好者从保留相似项目的逻辑中分离出来。函数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 的原则之一,我会用这样的库做非常不同的事情,特别是避免累加器对象的突变。但这应该可行。

【讨论】:

  • 我喜欢“更好”的想法 - CE - 持续附魔
【解决方案3】:

以下是您如何使用reduce 数组理解“一次性”完成的:

const result =
        [{ paragraph: "D" }, { paragraph: "A" }, { paragraph: "ABC" }, { paragraph: "AB" }, { paragraph: "A" }, { paragraph: "DEFG" }, { paragraph: "DE" }]
            .map(({ paragraph }) => paragraph)
            .sort()
            .reverse()
            .reduce((existingParagraphs, currentParagraph) => {

                if (existingParagraphs.length == 0
                    || !existingParagraphs.some(existingParagraph => existingParagraph.startsWith(currentParagraph))) {
                    existingParagraphs.push(currentParagraph);
                }
                return existingParagraphs;
            }, []);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多