Python:remove()不';它似乎起作用了

Python:remove()不';它似乎起作用了,python,Python,我找了一会儿,但找不到解决问题的办法。我对Python还是新手,所以有时我会和一些显而易见的事情做斗争。。。提前感谢您的建议 我有一个包含对象和这些对象的副本的列表,它们都有特定的名称:objects\u ext和duplicatedObject\u SREF\u ext。我想要的是,如果列表中有重复的对象,请检查原始对象是否也在列表中,如果在列表中,请从列表中删除重复的对象 我尝试使用remove()方法,因为列表中每个名称只能出现一次,但不起作用。这是我的密码: rawSelection =

我找了一会儿,但找不到解决问题的办法。我对Python还是新手,所以有时我会和一些显而易见的事情做斗争。。。提前感谢您的建议

我有一个包含对象和这些对象的副本的列表,它们都有特定的名称:
objects\u ext
duplicatedObject\u SREF\u ext
。我想要的是,如果列表中有重复的对象,请检查原始对象是否也在列表中,如果在列表中,请从列表中删除重复的对象

我尝试使用
remove()
方法,因为列表中每个名称只能出现一次,但不起作用。这是我的密码:

rawSelection = [u'crapacruk_high', u'doubidou_high', u'blahbli_high', u'crapacruk_SREF_high', u'doubidou_SREF_high', u'blahbli_SREF_high']
# objects with '_SREF_' in their names are the duplicated ones
for obj in rawSelection:
    if '_SREF_' in str(obj):
        rawName = str(obj).split('_')
        rootName = rawName [0]
        defName = rootName + '_' + '_'.join(rawName[2:])
        if defName in rawSelection:
            rawSelection.remove (obj)
# Always returns:
# [u'crapacruk_high', u'doubidou_high', u'blahbli_high', u'doubidou_SREF_high']
# Instead of:
# [u'crapacruk_high', u'doubidou_high', u'blahbli_high']

编辑:哦,忘了说只有原始对象也在列表中时,才必须从列表中删除重复对象。

您可以将for循环从列表中对象的
转到列表中对象的
(对象选择):
。这将修复您在迭代列表副本时遇到的问题。这样做的方式是,在对列表进行迭代时修改列表,从而导致出现问题

rawSelection = [u'crapacruk_high', u'doubidou_high', u'blahbli_high', u'crapacruk_SREF_high', u'doubidou_SREF_high', u'blahbli_SREF_high']

for obj in list(rawSelection):
    if '_SREF_' in str(obj):
        rawName = str(obj).split('_')
        rootName = rawName [0]
        defName = rootName + '_' + '_'.join(rawName[2:])
        if defName in rawSelection:
            rawSelection.remove (obj)

print(rawSelection)

这将满足您的要求(请注意,项目的显示顺序无关紧要):

这是通过迭代原始列表,并从每个项目中删除
“u SREF”
子字符串来实现的。然后将每个编辑的字符串对象添加到
集合
理解中(这就是
{}
括号的意思:正在创建一个新的
集合
对象)。然后,将
集合
对象转换回
列表
对象

这是因为对于
set
对象,不能有重复项,因此当尝试添加重复项时,它会失败(无声)。请注意,原始项目的顺序不保留

编辑:正如@peterdegloper在评论中指出的那样,这不适用于仅当原始项出现时才删除
\u SREF
项的约束。为此,我们将执行以下操作:

no_SREF_Set = {i for i in rawSelection if '_SREF_' not in i}
rawSelection = list({i.replace('_SREF', '') if i.replace('_SREF', '') in no_SREF_Set else i for i in rawSelection}) 
你可以把它组合成一行,但对我来说有点长:

rawSelection = list({i.replace('_SREF', '') if i.replace('_SREF', '') in {i for i in rawSelection if '_SREF_' not in i} else i for i in rawSelection})

这是通过创建一个没有
“u SREF”
的项目的
集合
,然后创建一个新的
列表
(与上述类似),该列表仅在
无SREF>集合
中出现项目的无
“u SREF”
版本时替换
“u SREF”

问题在于,您正在对迭代的同一个列表进行变异

当您从列表中删除
u'crapacruk\u SREF\u high'
时,它之后的所有内容都会向左移动(这在C源代码级别上完成),因此
obj
的值现在是
u'doubidou\u SREF\u high'
。然后for循环结束,
obj
成为列表中的下一个元素,
u'blahbli\u SREF\u high'

要解决此问题,您可以复制列表并获取

for obj in rawSelection[:]:
  ...

将问题分解为子任务

def get_orig_name(name):
    if '_SREF_' in name:
        return '_'.join(name.split('_SREF_'))
    else:
        return name
然后构造一个没有DUP的新列表

rawSelection = [u'crapacruk_high', 
                u'doubidou_high', 
                u'blahbli_high', 
                u'crapacruk_SREF_high', 
                u'doubidou_SREF_high', 
                u'blahbli_SREF_high']

uniqueList = [ n for n in rawSelection if ('_SREF_' not in n) or    
                                          (get_orig_name(n) not in rawSelection ) ]

print uniqueList

您可以使用
过滤器
获得相当干净的解决方案

def non_duplicate(s):
    return not('_SREF_' in s and s.replace('_SREF', '') in raw_selection)

filtered_selection = filter(non_duplicate, raw_selection)

修改列表时不要迭代列表。这是行不通的。从
列表
对象创建
对象会更好。它将删除重复项:
newobj=set(mylist)
EDIT:nevermind。没有意识到字符串是不一样的。@Morgan Thrapp你有其他选择吗?也许用发电机?感谢
u'doubidou'u high'
总是在
“u SREF”
版本之前出现吗?
rawSelection=[x代表x,如果“\u SREF”不在x或x.replace(“'u SREF',”)不在rawSelection中]
实际上,不,这违反了“只有原始对象也在列表中时,才能从列表中删除重复对象“。我也不确定是否已经确定不需要保留订单。OP说,复制版本不一定在原始版本之后,但这不完全是同一回事。@PeterdGlopper编辑了答案,以解决您在第一条评论中指出的问题。“不过,秩序确实没有得到维护。”斯图尔特正在工作。早些时候从控制台复制的错误。@PeterdGlopper我早些时候做的编辑有一个错误。现在是对的。
def non_duplicate(s):
    return not('_SREF_' in s and s.replace('_SREF', '') in raw_selection)

filtered_selection = filter(non_duplicate, raw_selection)