python从后面删除重复项_如何从python中的列表中删除重复项

本问题已经有最佳答案,请猛点这里访问。

我有一张单子:list = ['item1', 'item2', 'item3', 'item4']。

我想比较一下所有项目的相似性。

如果item2和item3相似,则结果为list = ['item1', 'item2', 'item4']。

编辑:

对不起,我的问题很困惑。

列表项是一组三角函数。我想删除列表中的类似项。

list = [('very','beauty','place'),('very','good','place'),('another','trigram','item')]

通过计算该列表中每个成对项目的jaccard相似性,如果成对项目的jaccard得分大于0.4,我称之为相似。在这个例子中,item1和item2是相似的。我想要的最后一个输出是:

list = [('very','beauty','place'),('another','trigram','item')]

这是计算JACCard分数的方法:

def compute_jaccard_index(set_1, set_2):

n = len(set_1.intersection(set_2))

return n / float(len(set_1) + len(set_2) - n)

你认为"相似"是什么?

它是可传递的吗?你有更好的例子(包括代码)吗?

当item2和item3相似时,您如何确定这两个元素中应保留哪些元素,应删除哪些元素?

此外,为什么每个人都认为"相似"意味着相同,因此认为集合是一个合适的解决方案?

"相似"是可传递的吗?如果a与b相似,b与c相似,那么a与c相似吗?例如,如果"first"与"first"相似,"first"与"list"相似,"first"与"list"相似?

抱歉,我只是编辑我的问题。

如果这些项目是字符串或数字,你是在寻找对象集。

中的例子:

In [1]: foo = [1, 32, 4, 5, 6, 5]

In [2]: set(foo)

Out[2]: {1, 4, 5, 6, 32}

In [3]: list(set(foo))

Out[3]: [32, 1, 4, 5, 6]

真的取决于你用类似的均方根。

不是接线员,是的。

@Marcin更新。

该解决方案将继续看,直到它已对两个元素没有任何期待的所有对的过滤。这不是一个有效的解决方案,它将继续看一遍又一遍的对,和它的使用,也没有使可能的传递性。但它的启动。

>>> from itertools import combinations

>>> def filterSimilar (d):

while True:

filteredOne = False

for s, t in combinations(d, 2):

if isSimilar(s, t):

d.remove(t)

filteredOne = True

break

if not filteredOne:

break

>>> d = ['asdf', 'asxf', 'foo', 'bar', 'baz']

>>> filterSimilar(d)

>>> d

['asdf', 'foo', 'bar']

实施例可能是一个isSimilar以下两个字符串之间的编辑距离的使用。

def levenshteinDistance (s, t):

if len(s) == 0:

return len(t)

if len(t) == 0:

return len(s)

return min(levenshteinDistance(s[:-1], t) + 1, levenshteinDistance(s, t[:-1]) + 1, levenshteinDistance(s[:-1], t[:-1]) + (0 if s[-1] == t[-1] else 1))

def isSimilar (s, t):

return levenshteinDistance(s, t) < 2

(请注意,我使用Levenshtein距离(在这个例子中是不相关的例子是一个比较)

用你的compute_jaccard_index函数,函数的isSimilar:现在看起来像这样

def isSimilar (s, t):

return compute_jaccard_index(s, t) > .4

然后用你的例子日期:

>>> lst = [{'very','beauty','place'},{'very','good','place'},{'another','trigram','item'}]

>>> filterSimilar(lst)

>>> lst

[{'very', 'beauty', 'place'}, {'item', 'trigram', 'another'}]

在def filterSimilar(d)中,缺少return d。

还有别的办法让它更快吗?

它不会丢失返回,因为它会就地更改传递的列表。一个使其更快的简单方法是记住您已经处理过的比较;或者,不要在删除某个内容时重新启动,而是记住,在将来的比较碰到它时跳过它,最后删除它。

这将工作,如果你有一个相似的功能比较:而直.

itemsToRemove = []

n = len(list)

for i in range(n):

for j in range(i+1,n):

if(similarTest(list[i], list[j]):

itemsToRemove.append(list[i])

break

return [item for item in list if item not in itemsToRemove]

当然,如果你是真的不一致性消除的项目,有人建议,然后将大的工作集。

使用某种散列解和dict,这几乎肯定会更好。而且,使用itertools计算笛卡尔积可能更好。

@Marcin不能散列两个单独元素之间的相似性。

@戳不,实际上你可以。这就是散列函数所做的。

@马金:例如,假设我定义两个字符串"相似",如果它们的列文斯坦距离小于或等于2。如果相似性不是等价关系,那么散列不会保留它(尽管有一些使用散列的近似值)。在这种情况下,您可以做得更好,例如使用K-D树。但是如果你对相似性的结构一无所知,如果它只是你调用的一个黑匣子函数,那么这就是它所得到的最好的结果。

@史蒂文杰索普,这都是真的。然而,等价关系是更常见的情况;在这种情况下,您确实可以"散列两个单独元素之间的相似性"。

你可以使用set.it将删除所有重复的元素,从列表中。

>>>list = [1,2,3,4,4,5,2,3,1]

>>>list =set(list)

>>>list

set([1, 2, 3, 4, 5])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值