Как преобразовать ввод файла последовательности dumbo в текст, разделенный табуляцией - PullRequest
0 голосов
/ 26 октября 2009

У меня есть входные данные, которые могут быть одним примитивом, списком или кортежем примитивов.

Я бы хотел свести его к списку, например так:

def flatten(values):
    return list(values)

Нормальный случай будет сглажен (что-то не так)

Но если значения = '1234', я бы получил ['1', '2', '3', '4'], но я бы хотел ['1234']

И если значения = 1, я бы получил TypeError: объект 'int' не повторяется, но я бы хотел [1]

Есть ли элегантный способ сделать это? Что я действительно хочу сделать, так это просто '\ t'.join (flatten (values))

Редактировать: Позвольте мне объяснить это лучше ...

Я хочу преобразовать двоичный файл последовательности hadoop в текстовый файл, разделенный плоской табуляцией, используя dumbo. Используя опцию формата вывода, -outputformat text

Dumbo - это оболочка Python для потоковой передачи Hadoop. Короче мне нужно написать функцию картографа:

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 (список (str (s) для s в flatten (seq)))

Ответы [ 3 ]

3 голосов
/ 26 октября 2009

Звучит так, как вы хотите 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))
1 голос
/ 26 октября 2009

Исходя из вашего повторного вопроса, эта 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. Это также предполагает, что клавиша ввода всегда будет отдельным элементом или списком элементов (а не списком списков) и что входные значения всегда будут списком элементов (опять же, не списками).

Это соответствует вашим требованиям?

0 голосов
/ 26 октября 2009

Я должен сказать, что заявленные требования являются странными, и я не думаю, что flatten - правильное название для такого рода операций. Но если вы действительно уверены, что это то, что вы хотите, то вот что я могу извлечь из вашего вопроса:

>>> 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...