So konvertieren Sie die Eingabe der Dumbo -Sequenzdatei in die Registerkarte getrennter Text

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

  •  06-07-2019
  •  | 
  •  

Frage

Ich habe Input, die eine einzelne Primitive oder eine Liste oder ein Tupel von Primitiven sein können.

Ich möchte es auf eine Liste flachen, wie SO:

def flatten(values):
    return list(values)

Der normale Fall würde abgeflacht sein (einige nichtablethatis nichtaString)

Aber wenn Werte = '1234', würde ich ['1', '2', '3', '4'] bekommen, aber ich würde ['1234'] wollen.

Und wenn Werte = 1, würde ich TypeError erhalten: 'int' Objekt ist nicht iterbar, aber ich möchte [1

Gibt es eine elegante Möglichkeit, dies zu tun? Was ich am Ende wirklich tun möchte, ist nur ' t'.join (flach (Werte))

EDIT: Lassen Sie mich das besser erklären ...

Ich möchte eine Hadoop -Binärsequenzdatei in eine flache Registerkarte, die mit DUMBO, mit getrennter Textdatei geführt werden. Verwenden der Option Ausgangsformat, -outputformat Text

Dumbo ist ein Python -Wrapper um Hadoop -Streaming. Kurz gesagt, ich muss die MAKPER -Funktion schreiben:

Def Mapper (Schlüssel, Werte) #einige Dinge ergeben k, v

wobei k eine Zeichenfolge aus dem ersten Teil des Schlüssels ist und der Wert eine Registerkarte getrennt ist, die den Rest des Schlüssels und die Werte als Zeichenfolgen enthält.

z.B:

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

oder komplizierter:

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

Der Eingabetaste oder -wert kann eine primitive oder eine Liste/ein Tupel von Primitiven sein.

Für den Out -Wert mache ich so etwas wie dieses v = ' t'.join (Liste (STR (s) für s in Flacher (seq)))

War es hilfreich?

Lösung

Klingt so, als ob du es willst itertools.chain(). Sie müssen jedoch Spezialfälle für Saiten benötigen, da sie wirklich nur iterables von Charakteren sind.

Aktualisieren:

Dies ist ein viel einfacheres Problem, wenn Sie es als rekursiver Generator tun. Versuche dies:

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

Dies gibt einen Iterator anstelle einer Liste zurück, aber er wird faul ausgewertet, was Sie wahrscheinlich sowieso wollen. Wenn Sie wirklich eine Liste benötigen, verwenden Sie einfach nur list(flatten(seq)) stattdessen.

Update 2:

Wie andere betont haben, wenn das, was Sie wirklich wollen str.join(), Dann müssen Sie alle Elemente in Saiten umwandeln. Dazu können Sie entweder ersetzen yield foo mit yield str(foo) Während meines oben oben genannten Beispiels oder einfacher Code wie folgt:

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

Andere Tipps

Basierend auf Ihrer angepassten Frage, dies mapper Funktion kann tun, was Sie wollen:

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

Es sieht so aus, als ob Sie das wahrscheinlich ändern möchten return zu einem yield. Dies setzt auch davon aus, dass der Eingabetaste immer ein einzelnes Element oder eine Liste von Elementen ist (keine Liste von Listen) und dass die Eingabewerte immer eine Liste von Elementen sind (wiederum keine Liste von Listen).

Erfüllt das Ihre Anforderungen?

Ich muss sagen, dass die angegebenen Anforderungen seltsam sind, und ich glaube nicht ebnen ist der richtige Name für diese Art von Operation. Aber wenn du es bist Ja wirklich Sicher, dass Sie dies wollen, dann kann ich das von Ihrer Frage ausgehen:

>>> 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'
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top