遍历Python列表并进行就地更改

时间:2015-12-02 05:02:28

标签: python list python-3.x

我的任务是删除一个特定元素的所有实例(在此示例中为' 6')并将它们移到列表的末尾。要求是遍历列表进行内联更改(不创建补充列表)。

输入示例:[6,4,6,2,3,6,9,6,1,6,5] 输出示例:[4,2,3,9,1,5,6,6,6,6,6]

到目前为止,我只能通过制作补充列表(打破任务要求)来实现这一目标,因此不允许使用此工作代码:

def shift_sixes(nums):
    b = []
    c = 0
    d = []

   for i in nums:
    if i == 6:
        b.insert(len(nums),i)
    elif i != 6:
        c = c +1
        d.insert(c,i)

   ans = d + b
   return ans

我还尝试了list.remove()list.insert(),但是在索引时遇到了麻烦(当我insert()然后将元素移到末尾时会移动):例如 -

a = [6,4,6,2,3,6,9,6,1,6,5]
  def shift_sixes(nums):
    for i in nums:
        if i == 6:
            nums.remove(i)
            nums.insert(nums[len(nums)-1], 0)
        elif i != 0:
            i
 shift_sixes(a)

此外,我尝试使用enumerate()函数,如下所示,但在b [idx]分配行的右侧遇到问题:

for idx, b in enumerate(a):
     a[idx] = ???

已阅读其他stackoverflow条目hereherehere,但它们并未解决元素到一端的移动问题。

非常感谢此列表遍历/现场切换问题的任何帮助。非常感谢。

EDIT @eph - 谢谢。这确实是一种优雅的回应。我相信它会通过我没有新的清单'需求?我当然打算更多地了解lambda及其用途 @falsetru - 谢谢你提醒append / pop组合(我试图通过list.remove()和list.insert()在原始查询中做的 @tdelaney - 谢谢你。不知何故,你的反应最接近我的尝试,但似乎没有通过[0,0,5]的测试。

7 个答案:

答案 0 :(得分:3)

在遍历时修改列表是个坏主意。您可以复制遍历,也可以在遍历期间生成新列表。

事实上,问题可以通过多种方式完成,例如:

>>> a.sort(key = lambda i: i == 6)
>>> a
[4, 2, 3, 9, 1, 5, 6, 6, 6, 6, 6]

答案 1 :(得分:1)

以相反方式迭代列表,pop元素(如果它是6),然后是append它。

xs = [6,4,6,2,3,6,9,6,1,6,5] 

for i in range(len(xs)-1, -1, -1):  # 10 to 0
    if xs[i] == 6:
        xs.append(xs.pop(i))

答案 2 :(得分:0)

为什么不尝试这样的事情?

基本上,方法是首先计算值的数量。 如果为0,则返回(因为如果为不在列表中的元素调用list.index方法,Python会产生ValueError。)

然后我们可以将该值的第一个可接受索引设置为列表的长度减去它在列表中出现的次数。

然后我们可以将list.pop / list.append组合在一起然后遍历列表,直到所有需要的值出现在列表的末尾。

def shift_value(lst, value):
    counts = lst.count(value)       # 5
    if not counts:
        return lst

    value_index = len(lst) - counts
    index = lst.index(value)
    while index != value_index:
        lst.append(lst.pop(index))
        index = lst.index(value)
    return lst

lst = [6,4,6,2,3,6,9,6,1,6,5]
print(shift_value(lst, 6))

编辑:这是非常低效的,上面建议的更好的答案。 这需要O(n ^ 2)时间,而不是O(n)时间。

答案 3 :(得分:0)

这里的关键术语是" In Line"。您这样做的方法是将每个num[i] = num[i+1]的{​​{1}}移动到列表的末尾。

i

答案 4 :(得分:0)

使用两个跑步者。首先从前到后检查6s,从头到尾指向最后一个项目,指向不是6.继续交换(a[i+1], a[i] = a[i], a[i+1])直到他们见面。

Catch:这在稳定排序中不稳定。但我并不认为这是一项要求。

在使用键盘的python解释器前尝试编写工作代码。

答案 5 :(得分:0)

如果您需要稳定的排序(即非6的元素的顺序应该保持不变),那么解决方案是:

def move_to_end(data, value):
    current = 0 # Instead of iterating with for, we iterate with index
    processed = 0 # How many elements we already found and moved to end of list
    length = len(data) # How many elements we must process
    while current + processed < length: # While there's still data to process
        if data[current] == value: # If current element matches condition
            data.append(data.pop(current)) # We remove it from list and append to end
            processed += 1 # Our index remains the same since list shifted, but we increase number of processed elements
        else: # If current element is not a match
            current += 1 # We increase our index and proceed to next element

if __name__ == '__main__':

    print
    print 'Some testing:'
    print

    for test_case in (
        [1, 9, 4, 6, 2, 7, 8, 6, 2, 2, 6], # Generic case
        [6, 6, 6, 6], # All items are 6
        [1, 7], # No items are 6
        [], # No items at all
    ):
        print 'Raw:', test_case
        move_to_end(test_case, 6)
        print 'Becomes:', test_case
        print

请注意,此解决方案不仅保留了不匹配元素的顺序,还保留了匹配元素的顺序。因此,例如,如果您更改检查条件为&#34;等于6&#34; to&#34;是偶数&#34;,与条件匹配的所有元素将被移动到列表的末尾,同时保留它们之间的顺序。

答案 6 :(得分:0)

为什么不保持简单?

a = [6,4,6,2,3,6,9,6,1,6,5]
def shift_sixes(nums):
    for i in range(0,len(nums)):
        if nums[i] == 6:
            nums.append(nums.pop(i))

>>> shift_sixes(a)
>>> a
[3, 9, 1, 5, 2, 4, 6, 6, 6, 6]