如果元素在列表中,请将其删除并返回新列表

时间:2016-02-04 15:35:38

标签: python python-3.x recursion

如果元素e位于列表L中,我们会被告知要将其删除并返回不带元素的新列表。

使用我当前的代码,我在第can only concatenate list (not "str") to list行收到错误M = [L[1]] + removeAll(e, L[2:])。有谁知道如何解决这个问题?

我们不允许使用forwhile语句。谢谢!

def removeAll(e, L):
    if e in L:
        if e == L[0]:
            M = [L[1]] + removeAll(e, L[2:])
        else:
            M = [L[0]] + removeAll(e, L[1:])
        return M
    return "{} is not in the list".format(e)

print (removeAll(42, [ 55, 77, 42, 11, 42, 88 ]))

3 个答案:

答案 0 :(得分:3)

当元素不在(剩余)列表中时,递归函数返回一个字符串:

if e in L:
    # ...
return "{} is not in the list".format(e)

因为您使用更短更短的列表调用此函数,所以在某些时候始终为真

然后尝试在两个地方将该字符串连接到一个列表:

M = [L[1]] + removeAll(e, L[2:])
# ...
M = [L[0]] + removeAll(e, L[1:])

不要返回字符串,返回列表 unmodified ,以便它可以连接到其他元素:

def removeAll(e, L):
    if e in L:
        if e == L[0]:
            M = [L[1]] + removeAll(e, L[2:])
        else:
            M = [L[0]] + removeAll(e, L[1:])
        return M
    return L  # no need to modify, the element is not present

您无需测试该元素是否在列表中的其他位置。仅测试第一个元素,如果匹配则不包括它。您还需要考虑L 的可能性:

def removeAll(e, L):
    if not L:
        return []
    head = [] if L[0] == e else L[:1]
    return head + removeAll(e, L[1:])

我再次使用切片创建一个包含一个元素的列表。

如果您必须测试该元素是否不在列表中,请在函数之外执行

original = [55, 77, 42, 11, 42, 88]
changed = removeAll(42, original)
if len(original) == len(changed):
    return "42 is not in the list"

当然,如果递归不是您的课程要求,那么您可以更好地使用列表推导来过滤值:

def removeAll(e, L):
    return [elem for elem in L if elem != e]

这将返回 new 列表,其中任何等于e的元素都会被过滤掉。

如果允许您就地更改列表,请使用list.remove()(并抓住ValueError

def removeAll(e, L):
    try:
        L.remove(e)
    except ValueError:
        pass
    return L

创建副本;对原始列表的任何其他引用都将看到相同的更改。

答案 1 :(得分:2)

您的解决方案几乎可行。你需要你的简单案例(e不在L中)来返回未修改的列表。别回信号。如果找不到该项,您可以选择发出print语句。

def removeAll(e, L):
    if e in L:
        if e == L[0]:
            M = [L[1]] + removeAll(e, L[2:])
        else:
            M = [L[0]] + removeAll(e, L[1:])
        return M
    else:            
        #print "{} is not in the list".format(e) # optional
        return L

这将是您的代码,只需最少的修复程序即可使其正常运行。

符合您要求的简短pythonic版本如下所示:

def removeAll(e, L):
    return filter(lambda x: x!=e, L)

或者,具有列表推导的等效代码:

def removeAll(e, L):
    return [x for x in L if x!=e]

我不知道这是否仍符合您的要求,因为那里有for(从技术上讲,列表理解不是for循环)。

答案 2 :(得分:0)

通用示例:

# declare sample space;
data1a = [0, 4, 8, 9, 12]
data2a = ['one','two','three']

# output pre-processed state;
print('Initial data')
print('Data 1a: {}'.format(data1a))
print('Data 2a: {}'.format(data2a))

print('=' *40)

# copy associated lists;
data1b = data1a.copy()
data2b = data2a.copy()

# process condition
if 4 in data1b:
    data1b.remove(4)

if 'two' in data2b:
    data2b.remove('two')

# output post-processed state with respect to pre-processed state
print('Data 1a: {}'.format(data1a))
print('Data 2a: {}'.format(data2a))

print('=' *40)

print('Data 1b: {}'.format(data1b))
print('Data 2b: {}'.format(data2b))

输出

Data 1a: [0, 4, 8, 9, 12]
Data 2a: ['one', 'two', 'three']
========================================
Data 1a: [0, 4, 8, 9, 12]
Data 2a: ['one', 'two', 'three']
========================================
Data 1b: [0, 8, 9, 12]
Data 2b: ['one', 'three']