繁体   English   中英

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

[英]How to reorder list in Python to avoid repeating elements?

我试图检查列表中是否有任何连续的重复元素,然后对其重新排序,以免重复。 如果那是不可能的,则返回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

您可以尝试概率方程式

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

[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

from itertools import groupby
>>> a =[1,2,2,1,1,3,3,3,3,3]
>>> s = [len(list(group)) for key, group in groupby(a)]
>>> s
[1, 2, 2, 5]
>>> max(s) < (sum(s)-max(s))
True

这是我使用非常有用的collections.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

如果“ None是序列中的有效值,或者您在任何程度上都关心稳定性,则需要进行一些改进。 如果序列中的元素不可散列,那么它将根本无法工作。

三元candidate = ...分配可能更清晰一些。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM