【问题标题】:Splitting a long tuple into smaller tuples将长元组拆分成更小的元组
【发布时间】:2011-04-26 05:30:27
【问题描述】:

我有一个像这样的长元组

(2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10)

我正在尝试将其拆分为一个元组,例如

((2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10))

我是 python 新手,不太擅长元组 o(2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10)r列表。我的朋友说我应该分开它,但我无法得到它-_-

我需要将元组拆分为具有 4 个元素的元组,稍后我将使用矩形绘制到带有 PIL 的图像。

【问题讨论】:

  • 如果您解释一下您对需要拆分的元组所做的事情会很好。通过这种方式,您可能会得到更多有用和信息丰富的答案。
  • @JohnD:FWIW,我认为这并不复杂或不寻常,需要很多上下文。

标签: python list split tuples


【解决方案1】:

嗯,有一个成语:

def grouper(n, iterable):
    args = [iter(iterable)] * n
    return zip(*args)

t = (2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10)
print grouper(4, t)

但是解释起来有点复杂。 the itertools receipes 中列出了一个稍微更通用的版本。

你也可以自己切片元组

parts = (t[0:4], t[4:8], t[8:12], t[12:16])

# or as a function
def grouper2(n, lst):
    return [t[i:i+n] for i in range(0, len(t), n)]

这可能是你朋友的意思。

【讨论】:

  • 我不会称之为惯用语——我以前从未见过它,我花了几秒钟才弄清楚发生了什么。这没有什么问题,但当然,一定要记录和 doctest。
  • 顺便说一句,我强烈推荐return itertools.izip(*args),因此这可以通过不尝试消耗整个迭代器而与大型迭代器一起正常工作。一个好的测试输入是itertools.cycle((1,2,3))
  • 我在这里经常看到它,足以将其视为 Python 的“SO 方言”中的一个成语。
  • @Glenn Maynard:我见过并使用过 tit 几次,因为它几乎是对生成器中的项目进行分组的唯一方法。所以我想这就是为什么我认为它是一个成语,也因为它非常简洁;-) 无论如何,izip 总是一个好主意,但现在我将不使用额外的导入,只是为了简单起见。
  • 问题是人们不可避免地会按原样复制和粘贴代码。我不认为增加一个不太正确的版本是一种胜利,因为它减少了一行代码。
【解决方案2】:
>>> atup
(2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10)
>>> [ atup[n:n+4] for n,i in enumerate(atup) if n%4==0 ]
[(2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10)]

【讨论】:

  • 喜欢@ghostdog74 的回答是因为,即使最后一个元组中包含 1 个元素,它也会成为包含 1 个元素的最后一个元组,其他解决方案只是将 1 个元素的最后一个元组排除在外。
【解决方案3】:

另一个可能的答案(使用生成器):

 oldTuple = (2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10)
 newTuple = tuple(oldTuple[x:x+4] for x in range(0, len(oldTuple), 4))

【讨论】:

    【解决方案4】:

    前段时间我写过一个像 gist 这样的函数,可以在http://gist.github.com/616853找到

    def split(input_list,num_fractions=None,subset_length=None):
       '''                                                                                                                                
       Given a list/tuple split original list based on either one of two parameters given but NOT both,                                   
       Returns generator                                                                                                                  
       num_fractions : Number of subsets original list has to be divided into, of same size to the extent possible.                       
                       In case equilength subsets can't be generated, all but the last subset                                             
                       will have the same number of elements.                                                                             
       subset_length : Split on every subset_length elements till the list is exhausted.                                                  
    
       '''
       if not input_list:
           yield input_list #For some reason I can't just return from here : return not allowed in generator expression                   
       elif not bool(num_fractions) ^ bool(subset_length): #Will check for both the invalid cases, '0' and 'None'.. Oh Python :)          
           raise Exception("Only one of the params : num_fractions,subset_length to be provided")
       else:
           if num_fractions: #calcluate subset_length in this case                                                                        
               subset_length = max(len(input_list)/num_fractions,1)
    
           for start in xrange(0,len(input_list),subset_length):
               yield input_list[start:start+subset_length]
    
    
    
    >> list(list_split.split((2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10),subset_length=4))
     [(2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10)]
    

    代码比上面给出的解决方案要长,但涵盖了所有可能的序列拆分条件。

    【讨论】:

    • 谢谢,但上面的工作正常。保存代码,因为它可以在正确的地方非常有用。
    猜你喜欢
    • 2020-04-18
    • 2014-11-20
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 2020-03-12
    • 2018-09-20
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多