合并列表中的重复项? - 问题比看起来更复杂

Posted

技术标签:

【中文标题】合并列表中的重复项? - 问题比看起来更复杂【英文标题】:Merging duplicates in a list? - Question is more complex than it seems 【发布时间】:2011-01-07 18:57:02 【问题描述】:

所以我在数据库中有一个庞大的条目列表 (MySql)

我在创建我的网络应用程序时使用 PythonDjango

这是我正在使用的基本 Django 模型:

class DJ(models.Model):
    alias = models.CharField(max_length=255)
    #other fields...

在我的数据库中现在重复

例如。 超越超越超越DJ超越磁盘玩笑超越,...

这是一个问题...因为它在我的数据库和我的应用程序中炸了一个大洞。


我相信其他人也遇到过这个问题并考虑过。

我的想法如下:

创建一组规则以便无法创建新条目?

例如。 “超越 DJ” 不能 创建是因为 “Above & Beyond” 位于 数据库

以某种方式将这些别名相互关联?

例如。将 “DJ 超越”“超越”

联系起来

我真的不知道如何继续处理这个问题,即使有人可以为我指出一个非常有帮助的方向。

任何帮助将不胜感激!谢谢各位。

【问题讨论】:

它看起来绝对更复杂,而且看起来相当复杂!处理自然语言相当复杂,我会留意这个问题。 这不是“更复杂”。这是“约束不佳”。 “以某种方式将这些别名相互关联”?这是什么意思? 【参考方案1】:

我猜你可以根据 Levenshtein distance 做一些事情,但没有真正的方法可以自动执行此操作 - 无需创建相当复杂的基于规则的系统。

除非您可以定义一个可以适用于任何xy 的规则系统,无论x 是否与y 重复,否则您将不得不以一种模糊的、人性化的方式处理这个问题方式。

Stack Overflow 有一个相当不错的方法来处理这个问题 - 如果某些东西 可能 是重复的,则警告用户,基于 Levenshtein 距离(可能还有某种规则引擎)之类的东西,然后允许如果其他用户忽略警告,您的一部分用户会将内容合并为重复项。

【讨论】:

谢谢!这适用于 "Above and Beyond""Above & Beyond" 吗? 如果您的意思是“Above and Beyond”和“Above & Beyond”的 Levenshtein 距离是多少,答案是 3(2 次删除 + 1 次编辑)。它是否“有效”取决于您如何处理该数字(您是否认为“Above & Beyond”与“Above not Beyond”相同,Levenshtein 距离也为 3?)。 您可能还想考虑使用单词而不是字符的 Levenshtein 距离 - 那么 DJ Above and BeyondAbove and Beyond 的距离为 1。当然,DJ MikeDJ Steve 的距离也会为 1,即使它们显然没有互相扯掉。由于这样的情况,没有不需要人工逐案检查的通用解决方案。 你是对的,但似乎是我唯一的选择之一。 Above and behind会接近​​Above and Beyond吗? "Levenshtein distance using words" 我可以通过使用停用词让它变得更好吗?无论如何,非常感谢您的贡献,我现在有很多发现和实验。 :)【参考方案2】:

从您提供的示例中,听起来您遇到的自然语言问题多于精确匹配问题。鉴于自然语言匹配本质上是不精确的,您不太可能提出完美的解决方案。

字符串距离实际上不起作用,因为算法上接近的字符串在语义上可能不接近(例如,“DJ Above & Beyond”应该匹配“Above and Beyond”而不是“DJ Above & Beyond 2”,后者更接近Levenshtein 距离。 自然语言解析的一些廉价替代方案是soundex,它将通过语音匹配,以及Stemming,它删除前缀/后缀以对词干进行规范化。我想你可以创建一个词根的链接列表,但这也不是非常准确。 如果这是一个用户交互程序,您可以向用户回显“near misses”,例如“你打算输入其中之一吗?” 您可以通过某种方式对条目进行规范化,以便不同的条目映射到相同的规范化值(例如,大小写规范化、“&”->“与”等,等等,上述一些建议可能是朝着这个方向迈出的一步) 来查找未遂事件或将多个输入映射到单个值。

添加我的经验仅适用于英语的警告,例如一个英文的 PorterStemmer 不会识别你放在那里的一个法语标题。

【讨论】:

谢谢史蒂夫,你的回答中有很多有用的信息。 stemming 如何为 “Above and Beyond”“DJ Above & Beyond” 工作?乍一看,这听起来像是一种标准化“昵称”的方式,我还没有在心理上处理它的实用性。 :) 词干是一个基于词的过程,而不是基于短语的过程。这个想法是将语法形式规范化到它们的词干,例如Ran, Run, Running -> Run,基本上是通过编码后缀、去除前缀以及许多特殊情况。除非它已经完成,否则会带你永远,代码示例就在那里。我在想你可以把一个短语转换成一个词干的链接列表。我敢肯定在某些情况下这也会中断(例如“Dumb and Dumber”->“Dumb and Dumberer”),因为您尝试做的本质上是一个模糊问题。也许与其他策略相结合......【参考方案3】:

我认为这更像是一个社会问题而不是编程问题。像这样的自然语言处理的任何类型的编程解决方案都将是错误的并且容易出错。很难区分接近的事物,但与您所说的那种不受欢迎的重复有合理的不同。

正如 Dominic 所提到的,Stack Overflow 的标记系统是一个很好的模型。它向用户提供提示,鼓励他们在适当的情况下使用现有标签(用户键入时下拉列表),它允许受信任的用户重新标记个别问题,并且允许版主进行大规模重新标记。

这确实是一个必须有人直接参与的过程。

【讨论】:

【参考方案4】:

这不是一个完整的解决方案,但我有一个想法:

class DJ(models.Model):
    #other fields, no alias!

class DJAlias(models.Model):
    dj = models.ForeignKey(DJ)

这将允许您为同一个 dj 拥有多个别名。

但是您仍然需要找到一种正确的方法来确保将别名添加到正确的 dj。请参阅Dominics 帖子。

但是,如果您将一个别名与指向一个 dj 的其他几个别名进行对比,算法可能会更好。

【讨论】:

【参考方案5】:

您可以尝试仅针对此实例解决此问题(将“&”替换为“&”,将“DJ”替换为“磁盘笑话”或忽略“DJ”等)。如果你的桌子只包含 DJ,你可以设置一堆这样的规则。 如果您的表格包含更多不同的东西,您将不得不采用更结构化的方法。您能否提供数据集的样本?

【讨论】:

嗨 Lex,感谢您的回答。列表中只有 DJ,但别名变化很大,例如。 “DJ Lex” 可以写成 “LEX”,但也有简单的名字“Sasha” 【参考方案6】:

首先,编程任务(如前所述的 NLP 等)当然很有趣。但如前所述,以完美为目标有点矫枉过正。

但另一种观点如前所述(“社交”),谁输入了数据,谁查看了它,它应该持续多长时间和正确程度?所以这是一个命名约定问题,让我想起了伟大的项目 musicbrainz.org - 如果您的网站“正常工作”还是您更喜欢遵循标准,在后一种情况下,我会沿着 mb 项目定位自己 - 如果您没有没做过,没听说过。 IE。 Above & Beyond 见这里:他们定义了别名,他们使用它来匹配用户搜索。 http://musicbrainz.org/show/artist/aliases.html?artistid=58438 另请查看 wiki 中的 Artist_Alias 页面。

数据模型值得一看,甚至还有几个用于同步数据的 API 绑定,也在 python 中。

【讨论】:

谢谢groovehunter!这是一个很好的信息来源,可以将我的问题放在上下文中。【参考方案7】:

如何将模型更改为“别名”,使其成为其他表的键列表,如下所示(跳过“the”、“and”等小词): 1 => 上面; 2 => 超越; 3 => 磁盘; 4 => 开玩笑;

然后,当您要插入新记录时,只需检查表中已有多少标题中的重要单词并匹配当前存在的模型实体。如果超过 50%(例如)可能是巧合,您可以向访问者展示它们的列表并询问“您是指其中的一些吗”。

【讨论】:

感谢您的回复 llian lliev!你说得对,我应该跳过单词,我发现他们称这些词为“停用词”。【参考方案8】:

看起来fuzzywuzzy 非常适合您的需求。

This article 解释了它的设置原因,它非常符合您的要求——基本上,用于处理两个不同事物名称略有不同的情况:

我们最经常遇到的一个令人沮丧的问题是试图弄清楚两个门票清单是否针对同一个现实生活中的事件(也就是说,没有获得我们实习生大军的帮助)。 … 为此,我们构建了一个“模糊”字符串匹配例程库来帮助我们。

【讨论】:

【参考方案9】:

如果您只关注艺术家姓名或通常与媒体相关的名称,那么只使用 last.fm 或 echonest 的 API 可能会更好,因为它们已经拥有庞大的规则集和庞大的数据库可供选择。

【讨论】:

以上是关于合并列表中的重复项? - 问题比看起来更复杂的主要内容,如果未能解决你的问题,请参考以下文章

在 Dart 中合并两个对象列表

按元素名称组合/合并列表(列表中的列表)

Android中的多行列表视图[重复]

javascript中的IndexOf方法比遍历数组更有效吗?

在Python中合并列表项[重复]

合并字典列表以删除所有重复项