Как преобразовать входные данные файла dumbo sequence в текст, разделенный табуляцией

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

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня есть input, который может быть одним примитивом, списком или кортежем примитивов.

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

def flatten(values):
    return list(values)

Нормальным случаем было бы сгладить (someiterablethatisn'tastring)

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

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

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

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

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

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')

Входной ключ или значение может быть примитивом или списком / кортежем примитивов Я хотел бы функцию "flatten", которая может обрабатывать что угодно и возвращать список значений.

Для значения out я сделаю что-то вроде этого v = ' '.join(list(str(s) для s в flatten(seq)))

Это было полезно?

Решение

Звучит так, как будто ты хочешь 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