2009-10-26 44 views
0

我有輸入,它可能是單個圖元或列表或圖元元組。如何將Dumbo序列文件輸入轉換爲製表符分隔的文本

我想拉平它只是一個列表,像這樣:

def flatten(values): 
    return list(values) 

正常情況下會被壓扁(someiterablethatisn'tastring)

但是,如果值= '1234',我'''','2','3','4'],但我想['1234']

如果值= 1,我會得到TypeError:'int'對象是不可迭代的,但我想[1]

有沒有一個優雅的方式 去做這個? 我真正想要的到底做的只是「\ t'.join(壓扁(值))

編輯:讓我來解釋這更好的...

我想轉換一個Hadoop二進制序列文件轉換爲使用dumbo的平面選項卡分隔文本文件。使用輸出格式選項,輸出格式文本

Dumbo是一個圍繞hadoop流的python包裝。總之我需要寫映射器功能:

DEF映射器(鍵,值) #do一些東西 產量K,V

其中k是從關鍵中的第一部分的字符串,和值是包含鍵的其餘部分和值作爲字符串的製表符分隔字符串。

例如:

input: (123, [1,2,3]) 
output: ('123', '1\t2\t\t3') 

或更復雜的:

input: ([123, 'abc'], [1,2,3]) 
output: ('123', 'abc\t1\t2\t\t3') 

輸入鍵或值可以是一個或多個圖元 的我想要「變平」的列表和/ tuple函數可以處理任何事情,並返回一個值列表。

對於超出價值,我會做這樣的事情 V =「\ t'.join(名單(STR(S)對於s的扁平化(SEQ)))

+0

這是怎麼回事? http://stackoverflow.com/questions/716477/join-list-of-lists-in-python – 2009-10-26 16:33:22

+2

通常術語'flatten'表示你想要將嵌套列表壓扁成單個列表(例如'[1,2, [3,4,5,6]]''到'[1,2,3,4,5,6]')。你要求的東西似乎稍有不同。如果你最終會將它提供給'str.join',你將需要將每個元素轉換爲一個字符串,而你在這個過程中。 – 2009-10-26 16:40:14

+0

Duplicate:http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python加上一些列表的混淆。 '1'不是一個列表,不能被壓扁;首先它必須被製成一個清單。 'str'已經是一個序列,所以請更具體地說明應該發生什麼。 – 2009-10-26 17:06:52

回答

3

聽起來像是你想itertools.chain() 。但是,您需要特殊字符串,因爲它們實際上只是字符的迭代。

更新

這是一個非常簡單的問題,如果你這樣做是一個遞歸發電機。試試這個:

def flatten(*seq): 
    for item in seq: 
     if isinstance(item, basestring): 
      yield item 
     else: 
      try: 
       it = iter(item) 
      except TypeError: 
       yield item 
       it = None 
      if it is not None: 
       for obj in flatten(it): 
        yield obj 

這返回一個迭代器,而不是一個名單,但它懶洋洋地評估,這可能是你想要的要多。如果您真的需要一個列表,請改爲使用list(flatten(seq))

更新2

正如其他人所指出的,如果你真的想要的是這種傳遞到str.join(),那麼你需要將所有的元素轉換爲字符串。要做到這一點,你可以替換上面用yield foo整個yield str(foo)我的例子,或只使用如下代碼:

"\t".join(str(o) for o in flatten(seq)) 
0

我必須說的是,規定要求是奇怪,我不認爲壓扁是這種手術的正確名稱。但是,如果你真的肯定這是你想要的,那麼這就是我可以從你的問題提煉:

>>> import itertools 
>>> def to_list_of_strings(input): 
...  if isinstance(input, basestring): # In Py3k: isinstance(input, str) 
...   return [input] 
...  try: 
...   return itertools.chain(*map(to_list_of_strings, input)) 
...  except TypeError: 
...   return [str(input)] 
... 
>>> '\t'.join(to_list_of_strings(8)) 
'8' 
>>> '\t'.join(to_list_of_strings((1, 2))) 
'1\t2' 
>>> '\t'.join(to_list_of_strings("test")) 
'test' 
>>> '\t'.join(to_list_of_strings(["test", "test2"])) 
'test\ttest2' 
>>> '\t'.join(to_list_of_strings(range(4))) 
'0\t1\t2\t3' 
>>> '\t'.join(to_list_of_strings([1, 2, (3, 4)])) 
'1\t2\t3\t4' 
+0

這很接近,但它會失敗,並且'to_list_of_strings([1,2,(3,4)])' - 它應該返回'[「1」,「2」,「3」,「4」]'而是返回'[「1」,「2」,「(3,4)」]' – 2009-10-26 16:48:51

+0

@Daniel:我實際上認爲OP不是那麼平坦。我會更新答案。 – Stephan202 2009-10-26 16:55:39

+0

不好意思,我的問題不是很清楚 – Tim 2009-10-26 17:31:16

1

根據您的重述問題,這mapper功能可能會做你想要什麼:

def mapper(key, values): 
    r"""Specification: do some stuff yield k, v where k is a string from the 
    first part in the key, and value is a tab separated string containing the 
    rest of the key and the values as strings. 

    >>> mapper(123, [1,2,3]) 
    ('123', '1\t2\t3') 

    >>> mapper([123, 'abc'], [1,2,3]) 
    ('123', 'abc\t1\t2\t3') 
    """ 
    if not isinstance(key, list): 
     key = [key] 
    k, v = key[0], key[1:] 
    v.extend(values) 
    return str(k), '\t'.join(map(str, v)) 

if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

看起來你可能想要將return更改爲yield。這也假定輸入鍵將始終是單個項目或項目列表(不是列表列表),並且輸入值始終是項目列表(再次列出項目列表)。

這是否符合您的要求?

相關問題