Type error: Can only join an iterable Python-error

Type error: Can only join an iterable Python-error

首先,我已经看过关于同一主题的这些帖子:

"Can only iterable" Python error

python error-can only join an iterable

但遗憾的是,其中 none 似乎回答了我的问题。我想要一个列表,并按大小对所有非 -1 值进行排序,然后 return -1 到它们的原始位置。这是我的代码:

def sortByHeight(a):
    treeLocations = []
    for everyHeight in a:
        if everyHeight == -1:
            treeLocations.append([(len(a)-a.index(everyHeight)), (a.index(everyHeight)-1)])
            a.remove(-1)
    people = sorted(a)
    for everyPair in treeLocations:
        one = everyPair[1]
        two = everyPair[0]
        people[one:two] = -1
    return(people)

sortByHeight([-1, 150, 190, 170, -1, -1, 160, 180])

我的代码在第 11 行抛出错误:TypeError: can only assign an iterable。 这是什么意思,我该如何解决?

为了直接解决您询问的问题,您正在尝试将单个元素分配给一个切片(这需要一个可迭代对象)。清理示例中的一些内容,您可能会执行以下操作:

def sortByHeight(a):
    # Get indices of all -1's
    treeLocations = [index for index, height in enumerate(a) if height == -1]
    # Get list of all others
    people = [height for height in a if height != -1]
    # Sort list of others
    people = sorted(people)
    # Re-insert -1's
    for everyIndex in treeLocations:
        people.insert(everyIndex, -1)
    return(people)

通常不是从您正在迭代的列表中删除项目的好主意,如果您不小心,可能会导致意外结果。参见 Remove items from a list while iterating。正如 John Machin 所说,这有点像锯掉你所坐的树枝。 ;)

此外,从列表中删除项目效率不高:必须从头开始扫描列表,直到找到匹配的项目,然后当删除该项目时,所有后续项目都必须向下移动到填补空白。最好执行过滤操作,从您希望保留的项目构建新列表。


这是执行该排序的一种相当有效的方法。诀窍是提取我们要排序的项目,对它们进行排序,然后构建一个列表,将排序后的项目放入适当的位置。

def sortByHeight(seq):
    ''' sort `seq`, leaving any items equal to -1 in place '''
    # Extract items != -1
    a = [u for u in seq if u != -1]
    a.sort()
    it = iter(a)
    result = []
    for u in seq:
        result.append(u if u == -1 else next(it))
    return result

data = [-1, 150, 190, 170, -1, -1, 160, 180]
print(data)
result = sortByHeight(data)
print(result)

输出

[-1, 150, 190, 170, -1, -1, 160, 180]
[-1, 150, 160, 170, -1, -1, 180, 190]

赋值的目标是列表的切片。如果你想给一个切片赋值,它必须是 Python 可以迭代的东西——列表、元组和字符串都是 "iterables" 的例子。所以

people[one:two] = [-1]

将用单个元素替换切片中的元素-1。您可以在交互式解释器中轻松测试:

>>> my_list = [1, 2, 3, 4, 5]
>>> my_list[2:3] = ['a', 'b', 'c']
>>> my_list
[1, 2, 'a', 'b', 'c', 4, 5]
>>> my_list[2:3] = -1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
>>> 

如果您想用 -1 替换所有元素,那么一种可能的公式是使用列表乘法来给出正确长度的序列:

people[one:two] = [-1] * (two-one)

除了我在评论中提到的错误之外,如果您想以更简单的方式执行此操作,请尝试以下操作:

def sortByHeight(a):
    result = sorted(v for v in a if v != -1)  # first sort all non -1 fields
    for i, v in enumerate(a):  # enumerate and iterate over the original list
        if v == -1:  # if the current value is -1
            result.insert(i, -1)  # put it back into the sorted list at its original position
    return result