如何在Python中对列表重新排序以避免重复元素?

如何在Python中对列表重新排序以避免重复元素?,python,list,duplicates,sequence,Python,List,Duplicates,Sequence,我试图检查列表是否有任何连续的重复元素,然后对其重新排序以避免重复。如果这是不可能的,那么返回False。例如: checkRepeat([1,2]) Out[61]: [1, 2] checkRepeat([1,2,2]) Out[62]: [2, 1, 2] checkRepeat([1,2,2,1,1]) Out[63]: [1, 2, 1, 2, 1] checkRepeat([1,2,2,1,1,3,3,3,3]) Out[64]: [1, 3, 1, 3, 2, 1, 3, 2

我试图检查列表是否有任何连续的重复元素,然后对其重新排序以避免重复。如果这是不可能的,那么返回False。例如:

checkRepeat([1,2])
Out[61]: [1, 2]

checkRepeat([1,2,2])
Out[62]: [2, 1, 2]

checkRepeat([1,2,2,1,1])
Out[63]: [1, 2, 1, 2, 1]

checkRepeat([1,2,2,1,1,3,3,3,3])
Out[64]: [1, 3, 1, 3, 2, 1, 3, 2, 3]

checkRepeat([1,2,2,1,1,3,3,3,3,3])
Out[65]: [3, 1, 3, 2, 3, 1, 3, 1, 3, 2]

checkRepeat([1,2,2,1,1,3,3,3,3,3,3])
Out[66]: [3, 1, 3, 1, 3, 1, 3, 2, 3, 2, 3]

checkRepeat([1,2,2,1,1,3,3,3,3,3,3,3])
Out[67]: False
这是我的。有更优雅的解决方案吗

from itertools import groupby
def checkRepeat(lst,maxIter=1000):
    """Returns a list that has no repeating elements. Will try for a max of 1000 iterations by default and return False if such a list can't be found"""

    def hasRepeat(lst):
        """Returns true if there are any repeats"""
        return len([x[0] for x in groupby(lst)]) < len(lst)


    offset=numIter=0        
    while hasRepeat(lst) and numIter<maxIter:
        for i,curElt in enumerate(lst):
            try:
                if lst[i]==lst[i+1]:
                    lst[i+1],lst[(i+offset) % len(lst)] = lst[(i+offset) % len(lst)],lst[i+1] #swap j+1 with j+offset. wrap around the list
            except:
                break
        offset+=1
        numIter+=1
    if numIter==maxIter:
        return False
    else:
        return lst
从itertools导入groupby
def检查重复(lst,最大值=1000):
“”“返回一个没有重复元素的列表。默认情况下,将尝试最多1000次迭代,如果找不到这样的列表,则返回False”“”
def HASSREPEAT(lst):
“”“如果有任何重复,则返回true”“”
返回len([x[0]表示groupby中的x(lst)])而hasreat(lst)和numIter则可以尝试概率方程

重复次数最多的数字必须始终小于其他数字的计数

[1,2,2,1,1,3,3,3,3,3,3,3]
 7< (3+2) false

[1,2,2,1,1,3,3,3,3,3,3]
 6< (3+2)  true

 [1,2,2,1,1,3,3,3,3,3]
 5< (3+3)  true
[1,2,2,1,1,3,3,3,3,3,3]
7<(3+2)错误
[1,2,2,1,1,3,3,3,3,3,3]
6<(3+2)正确
[1,2,2,1,1,3,3,3,3,3]
5<(3+3)正确
代码

从itertools导入groupby
>>>a=[1,2,2,1,1,3,3,3,3]
>>>s=[len(列表(组))表示键,groupby(a)中的组]
>>>
[1, 2, 2, 5]
>>>最大值<(总和-最大值))
符合事实的

以下是我在使用非常有用的
集合实现的注释中提到的算法。Counter
类:

from collections import Counter

def check_repeat(sequence):
    if not sequence:
        return []
    element_counts = Counter(sequence)
    new_sequence = []
    elements_chosen = 0
    elements_needed = len(sequence)
    previous_element_chosen = None
    while elements_chosen < elements_needed:
        candidates_needed = 1 if previous_element_chosen is None else 2
        candidates = element_counts.most_common(candidates_needed)
        candidate = (candidates[0] if 
            (len(candidates) < 2 or candidates[0][0] != previous_element_chosen)
            else candidates[1])
        if candidate[1] <= 0:
            return False
        else:
            new_sequence.append(candidate[0])
            element_counts[candidate[0]] -= 1
            previous_element_chosen = candidate[0]
            elements_chosen += 1
    return new_sequence
从集合导入计数器
def检查_重复(顺序):
如果没有顺序:
返回[]
元素计数=计数器(序列)
新的_序列=[]
所选元素=0
所需元素=len(序列)
上一个元素所选元素=无
当所选元素小于所需元素时:
如果选择的前一个元素不是其他元素,则候选元素\u needed=1 2
候选元素=元素计数。最常见(需要候选元素)
候选人=(候选人[0]如果
(len(候选者)<2或候选者[0][0]!=先前选择的元素)
其他候选人[1])

如果候选者[1]如果您有需要改进的工作代码,它可能非常适合。只需头脑风暴一个算法,但我可能会建立每个元素的计数,然后添加一个非上一个元素的实例,该元素的未使用计数最高。如果在任何时候,所有非先前元素都有0个可用计数,则返回false。它应该只需要对原始列表进行两次遍历,一次计算元素,然后一次选择重新排序的列表中的每个元素。@Heslacher-从“是否有更优雅的解决方案”中,我假设OP有某种工作解决方案,并希望尽可能使其更优雅。@TigerhawkT3,摘自标题“如何在Python中对列表进行重新排序以避免重复元素?”这篇文章将以主题外的形式结束。但你是对的。我没有读这个问题,我的错。
from collections import Counter

def check_repeat(sequence):
    if not sequence:
        return []
    element_counts = Counter(sequence)
    new_sequence = []
    elements_chosen = 0
    elements_needed = len(sequence)
    previous_element_chosen = None
    while elements_chosen < elements_needed:
        candidates_needed = 1 if previous_element_chosen is None else 2
        candidates = element_counts.most_common(candidates_needed)
        candidate = (candidates[0] if 
            (len(candidates) < 2 or candidates[0][0] != previous_element_chosen)
            else candidates[1])
        if candidate[1] <= 0:
            return False
        else:
            new_sequence.append(candidate[0])
            element_counts[candidate[0]] -= 1
            previous_element_chosen = candidate[0]
            elements_chosen += 1
    return new_sequence