dumbo 시퀀스 파일 입력을 탭으로 구분된 텍스트로 변환하는 방법

StackOverflow https://stackoverflow.com/questions/1625757

  •  06-07-2019
  •  | 
  •  

문제

단일 기본 요소 또는 기본 요소의 목록 또는 튜플이 입력될 수 있습니다.

다음과 같이 목록으로 정리하고 싶습니다.

def flatten(values):
    return list(values)

일반적인 경우는 평평해질 것입니다.

그러나 값 = '1234'이면 ['1', '2', '3', '4']를 얻지만 ['1234']를 원합니다.

값이 1이면 TypeError가 발생합니다.'int' 객체는 반복 가능하지 않지만 [1]을 원합니다.

이를 수행하는 우아한 방법이 있습니까?결국 내가 정말로 하고 싶은 것은 ' '.join(Flatten(values)) 입니다.

편집하다:이것을 더 잘 설명하자면...

dumbo를 사용하여 hadoop 바이너리 시퀀스 파일을 플랫 탭으로 구분된 텍스트 파일로 변환하고 싶습니다.출력 형식 옵션인 -outputformat text 사용

Dumbo는 hadoop 스트리밍을 둘러싼 Python 래퍼입니다.간단히 말해서 매퍼 함수를 ​​작성해야 합니다.

def mapper (키, 값) #일부 물건은 k, v 수율

여기서 k는 키의 첫 번째 부분의 문자열이고 value는 나머지 키와 값을 문자열로 포함하는 탭으로 구분된 문자열입니다.

예:

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

또는 더 복잡함:

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

입력 키 또는 값은 프리미티브 또는 프리미티브의 목록/튜플 일 수 있습니다. 나는 무엇이든 처리 할 수 ​​있고 값 목록을 반환 할 수있는 "평평한"함수를 원합니다.

아웃 값을 위해, 나는이 v = ' t'.join과 같은 일을 할 것이다 (평평한 s에 대한 str (s)).

도움이 되었습니까?

해결책

당신이 원하는 것 같네요 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))

다른 팁

당신의 재정의 질문에 근거하여, 이것 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 a yield. 또한 입력 키는 항상 단일 항목 또는 항목 목록 (목록 목록이 아님)이며 입력 값은 항상 항목 목록 (다시 목록 목록이 아닌)이라고 가정합니다.

그것은 당신의 요구 사항을 충족합니까?

언급 된 요구 사항은 이상하다고 말해야하며 생각하지 않습니다. 단조롭게 하다 이런 종류의 작업에 적합한 이름입니다. 하지만 당신이 진짜 이것이 당신이 원하는 것임을 확인하십시오. 그렇다면 이것이 내가 당신의 질문에서 벗어날 수있는 것입니다.

>>> 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'
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top