Codice utile che utilizza ridurre()?

Qualcuno qui sono utili codice che utilizza ridurre() funzione in python? C’è qualche codice di diverso dal solito + e * che vediamo negli esempi?

Riferimento Il destino di ridurre() in Python 3000 dal GvR

  • from functools import reduce permette di utilizzare lo stesso codice funziona su entrambi Python 2 e 3.
InformationsquelleAutor cnu | 2008-08-19

 

24 Replies
  1. 64

    Gli altri usi che ho trovato per oltre + e * sono stati con e e o, ma ora abbiamo any e all per sostituire quei casi.

    foldl e foldr fare in Regime di tanto…

    Ecco alcuni simpatici usi:

    Appiattire un elenco

    Obiettivo: girare [[1, 2, 3], [4, 5], [6, 7, 8]] in [1, 2, 3, 4, 5, 6, 7, 8].

    reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])

    Elenco di cifre di un numero

    Obiettivo: girare [1, 2, 3, 4, 5, 6, 7, 8] in 12345678.

    Brutto, lento:

    int("".join(map(str, [1,2,3,4,5,6,7,8])))

    Abbastanza reduce modo:

    reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)
    • Perché si aggiunge il “, 0” nell’ultimo esempio? Per essere in grado di gestire l’eventualità di una lista vuota, o ci sono altri motivi?
    • Per la spianatura di un elenco, preferisco elenco(itertools.catena(*nested_list))
    • penso che è sempre necessario un primo elemento. in questo caso, ti 0. in caso contrario, che cosa sarebbe ‘d’ essere quando guardando il primo elemento?
    • quando no valore iniziale è dato, ridurre appena si applica la riduzione per il primo due elementi. se no valore iniziale è dato e vi è un solo elemento, quindi non avviene la riduzione…. Io penso che…
    • Che non gestisce liste nidificate.
    • Il reduce soluzione non sia!
    • somma([[1, 2, 3], [4, 5], [6, 7, 8]], [])
    • Questo è un terribile pezzo di codice… La cosa migliore GvR fatto è stato rimuovere ridurre da builtins.
    • Bonvallet: list(itertools.chain.from_iterable(nested_list))
    • E ‘ anche utile per le operazioni bit per bit. Che cosa succede se si vuole prendere l’or bit a bit di un gruppo di numeri, per esempio, se avete bisogno di convertire le bandiere da un elenco per una maschera di bit?
    • Si chiama l’ultimo esempio ridurre abbastanza? IMHO, è nulla, ma abbastanza. Per me, int(“”.join(str(i) for i in range(1, 9))) è molto più leggibile.
    • a un certo punto è una questione di gusti. ma il reduce modo è molto più efficiente, almeno da un algoritmo (forse l’overhead di fare il calcs via lambda è maggiore di un’altra strada. si avrebbe bisogno di benchmark.)
    • Facendo alcuni parametri di riferimento, il ‘brutto’ il modo più veloce per gli elenchi di grandi dimensioni. timeit.repeat('int("".join(map(str, digit_list)))', setup = 'digit_list = list(d%10 for d in xrange(1,1000))', number=1000) prende ~0.09 secondi mentre timeit.repeat('reduce(lambda a,d: 10*a+d, digit_list)', setup = 'digit_list = list(d%10 for d in xrange(1,1000))', number=1000) prende 0.36 secondi (circa 4 volte più lento). Fondamentalmente la moltiplicazione per 10 diventa costoso quando la lista si grande, mentre un int str e concatenazione soggiorni a buon mercato.
    • Concesso, sì per piccole liste (taglia 10) quindi ridurre il metodo è di 1,3 volte più veloce. Tuttavia, anche in questo caso, evitando di ridurre e fare un semplice ciclo è ancora più veloce timeit.repeat('convert_digit_list_to_int(digit_list)', setup = 'digit_list = [d%10 for d in xrange(1,10)]\ndef convert_digit_list_to_int(digits):\n i = 0\n for d in digits:\n i = 10*i + d\n return i', number=100000) prende 0.06 s, timeit.repeat('reduce(lambda a,d: 10*a+d, digit_list)', setup = 'digit_list = list(d%10 for d in xrange(1,10))', number=100000) prende 0,12 s e la conversione di cifre a str metodo prende 0.16 s.
    • Per #2, un elenco di cifre di un numero. Vorrei fare qualcosa di simile a questo: int(''.join([str(i) for i in l])). Un po ‘ scomodo visto che ho il cast e la forza, ma è veloce (lista di comprensione e str.join). Ok, ho appena visto Victor Yan postato in precedenza. stessa cosa.
    • l) è più veloce di un elenco di comprensione, ma riduci il metodo è più veloce
    • href=”https://gist.github.com/zed/ac0f5df365dffdb94f97476a89d38c8f” >ottengo risultati simili a pypy: int(''.join essere più veloce di reduce() per N=1000 e reduce() è più veloce di int(''.join per N=10`.
    • La “lista di cifre” soluzione si estende a base conversione (dato un elenco di valori delle cifre), e per il polinomio di valutazione utilizzando Horner metodo (dato un elenco di coefficienti da alto a basso).

  2. 50

    reduce() può essere utilizzato per trovare Il minimo comune multiplo per 3 o più numeri:

    #!/usr/bin/env python
    from fractions import gcd
    from functools import reduce
    
    def lcm(*args):
        return reduce(lambda a,b: a * b // gcd(a, b), args)

    Esempio:

    >>> lcm(100, 23, 98)
    112700
    >>> lcm(*range(1, 20))
    232792560
    • Che cosa è lcm nella seconda riga?
    • segui link nella risposta. lcm() restituisce il minimo comune multiplo di due numeri.
  3. 38

    reduce() potrebbe essere utilizzato per risolvere costellato di nomi (dove eval() è troppo pericoloso da usare):

    >>> import __main__
    >>> reduce(getattr, "os.path.abspath".split('.'), __main__)
    <function abspath at 0x009AB530>
  4. 12

    Penso ridurre è un sciocco di comando. Quindi:

    reduce(lambda hold,next:hold+chr(((ord(next.upper())-65)+13)%26+65),'znlorabggbbhfrshy','')
    • Mi piace anche l’ironia qui
  5. 11

    L’utilizzo di reduce che ho trovato nel mio codice prevedeva la situazione in cui ho avuto qualche struttura di classe per l’espressione logica e avevo bisogno di convertire un elenco di queste espressioni di oggetti di un insieme di espressioni. Ho già avuto una funzione make_and per creare un insieme dato di due espressioni, così ho scritto reduce(make_and,l). (Sapevo che la lista non era vuota; in caso contrario sarebbe stato qualcosa di simile a reduce(make_and,l,make_true).)

    Questo è esattamente il motivo che (alcuni) ai programmatori funzionali come reduce (o piega funzioni, in quanto tali funzioni sono in genere chiamati). Spesso ci sono già molti binari funzioni come +, *, min, max, concatenazione e, nel mio caso, make_and e make_or. Avere un reduce rende semplice per sollevare queste operazioni di liste (o alberi o quello che hai, per ripiegare le funzioni in generale).

    Naturalmente, in presenza di determinate istanze (come sum) sono spesso utilizzati, quindi non si vuole continuare a scrivere reduce. Tuttavia, invece di definire la sum con qualche ciclo for, si può facilmente definire con reduce.

    Leggibilità, come detto da altri, è effettivamente un problema. Si potrebbe obiettare, tuttavia, che il solo motivo per cui le persone a trovare reduce meno “chiaro” è perché non è una funzione che molte persone conoscono e/o utilizzo.

    • a guardia contro il vuoto lista si potrebbe sfruttare in corto circuito il comportamento di and operatore: L and reduce(make_and, L) se la restituzione di lista vuota è appropriato in questo caso
  6. 8

    Funzione di composizione: Se si dispone già di un elenco di funzioni che si desidera applicare in successione, ad esempio:

    color = lambda x: x.replace('brown', 'blue')
    speed = lambda x: x.replace('quick', 'slow')
    work = lambda x: x.replace('lazy', 'industrious')
    fs = [str.lower, color, speed, work, str.title]

    Quindi è possibile applicare tutti consecutivamente con:

    >>> call = lambda s, func: func(s)
    >>> s = "The Quick Brown Fox Jumps Over the Lazy Dog"
    >>> reduce(call, fs, s)
    'The Slow Blue Fox Jumps Over The Industrious Dog'

    In questo caso, il metodo di concatenamento può essere più leggibile. Ma a volte non è possibile, e questo tipo di composizione può essere più leggibile e manutenibile di un f1(f2(f3(f4(x)))) tipo di sintassi.

    • Un vantaggio è che è possibile modificare l’elenco di funzioni per applicare il codice.
  7. 7

    @Blair Conrad: Si potrebbe anche implementare il glob/ridurre utilizzando la somma, in questo modo:

    files = sum([glob.glob(f) for f in args], [])

    Questo è meno dettagliata di uno dei tuoi due esempi, è perfettamente Divinatori, ed è ancora solo una riga di codice.

    Quindi, per rispondere alla domanda originale, io personalmente cerco di evitare l’uso di ridurre, perché non è mai realmente necessario e trovo che sia meno evidente rispetto ad altri approcci. Tuttavia, alcune persone ottenere utilizzato per ridurre e preferisco di genericità elenco (soprattutto Haskell programmatori). Ma se non stai già pensando a un problema in termini di riduzione, probabilmente non avrete bisogno di preoccuparsi di utilizzo.

    • Sia sum e reduce portare a quadratica comportamento. Esso può essere fatto in un tempo lineare: files = chain.from_iterable(imap(iglob, args)). Anche se probabilmente non importa, in questo caso, a causa del tempo necessario per glob() per accedere a un disco.
  8. 6

    reduce può essere utilizzato per supportare incatenato attributo ricerche:

    reduce(getattr, ('request', 'user', 'email'), self)

    Naturalmente, questo è equivalente a

    self.request.user.email

    ma è utile quando il codice deve accettare un elenco arbitrario di attributi.

    (Concatenate attributi di lunghezza arbitraria sono comuni quando si tratta con Django modelli.)

  9. 4

    reduce è utile quando si ha bisogno di trovare l’unione o l’intersezione di una sequenza di set-come oggetti.

    >>> reduce(operator.or_, ({1}, {1, 2}, {1, 3}))  # union
    {1, 2, 3}
    >>> reduce(operator.and_, ({1}, {1, 2}, {1, 3}))  # intersection
    {1}

    (A prescindere dall’effettivo sets, un esempio di questi sono Django Q oggetti.)

    D’altra parte, se hai a che fare con bools, si dovrebbe utilizzare any e all:

    >>> any((True, False, True))
    True
  10. 3

    Sto scrivendo un comporre funzione per una lingua, in modo da costruire la funzione composta mediante ridurre insieme con il mio operatore apply.

    In un guscio di noce, di comporre un elenco di funzioni di comporre in un’unica funzione. Se ho una complessa operazione che viene applicata in più fasi, voglio mettere tutto insieme in questo modo:

    complexop = compose(stage4, stage3, stage2, stage1)

    Questo modo, posso poi applica un’espressione in questo modo:

    complexop(expression)

    E voglio che sia equivalente a:

    stage4(stage3(stage2(stage1(expression))))

    Ora, a costruire i miei oggetti interni, la voglio dire:

    Lambda([Symbol('x')], Apply(stage4, Apply(stage3, Apply(stage2, Apply(stage1, Symbol('x'))))))

    (Lambda classe costruisce una funzione definita dall’utente, e Applicare costruisce una funzione dell’applicazione.)

    Ora, ridurre, purtroppo, si piega il modo sbagliato, così ho finito utilizzando, circa:

    reduce(lambda x,y: Apply(y, x), reversed(args + [Symbol('x')]))

    Per capire cosa ridurre produce, tenta in REPL:

    reduce(lambda x, y: (x, y), range(1, 11))
    reduce(lambda x, y: (y, x), reversed(range(1, 11)))
  11. 3

    ridurre può essere utilizzato per ottenere l’elenco con la massima ennesimo elemento

    reduce(lambda x,y: x if x[2] > y[2] else y,[[1,2,3,4],[5,2,5,7],[1,6,0,2]])

    sarebbe tornato [5, 2, 5, 7] questa è la lista con max 3 elementi +

    • max(lst, key = lambda x: x: x[2])
  12. 3

    Ridurre non è limitato a scalare operazioni; può anche essere utilizzato per ordinare le cose in secchi. (Questo è quello che io uso per ridurre il più spesso).

    Immaginare un caso in cui si dispone di un elenco di oggetti, e si desidera ri-organizzare in modo gerarchico basato sulla proprietà memorizzati fisicamente in oggetto. Nel seguente esempio, creare una lista di oggetti metadati relativi agli articoli che codifica XML giornale con la articles funzione. articles genera un elenco di elementi XML, e poi le mappe attraverso di loro uno per uno, la produzione di oggetti che contengono alcune informazioni interessanti su di loro. Sul front-end, sto andando a voler consentire all’utente di sfogliare gli articoli di sezione/sottosezione/titolo. Quindi io uso reduce a prendere l’elenco degli articoli e restituire un unico dizionario che riflette la sezione/sottosezione/articolo gerarchia.

    from lxml import etree
    from Reader import Reader
    
    class IssueReader(Reader):
        def articles(self):
            arts = self.q('//div3')  # inherited ... runs an xpath query against the issue
            subsection = etree.XPath('./ancestor::div2/@type')
            section = etree.XPath('./ancestor::div1/@type')
            header_text = etree.XPath('./head//text()')
            return map(lambda art: {
                'text_id': self.id,
                'path': self.getpath(art)[0],
                'subsection': (subsection(art)[0] or '[none]'),
                'section': (section(art)[0] or '[none]'),
                'headline': (''.join(header_text(art)) or '[none]')
            }, arts)
    
        def by_section(self):
            arts = self.articles()
    
            def extract(acc, art):  # acc for accumulator
                section = acc.get(art['section'], False)
                if section:
                    subsection = acc.get(art['subsection'], False)
                    if subsection:
                        subsection.append(art)
                    else:
                        section[art['subsection']] = [art]
                else:
                    acc[art['section']] = {art['subsection']: [art]}
                return acc
    
            return reduce(extract, arts, {})

    Mi danno entrambe le funzioni qui perché penso che mostra come la mappa e ridurre possibile completano perfettamente a vicenda quando si lavora con oggetti. La stessa cosa avrebbe potuto essere realizzato con un ciclo for, … ma trascorrere qualche momento di grave con un linguaggio funzionale tende a farmi pensare in termini di mappa e ridurre.

    A proposito, se qualcuno ha un modo migliore per impostare le proprietà come sto facendo in extract, dove i genitori della proprietà che si desidera impostare potrebbero non esiste ancora, per favore fatemelo sapere.

  13. 3

    Non sono sicuro se questo è che cosa siete dopo, ma si può codice sorgente di ricerca su Google.

    Segui il link per una ricerca su ‘funzione:ridurre() lang:python’ su Google Code search

    A prima vista, i seguenti progetti di utilizzo reduce()

    • MoinMoin
    • Zope
    • Numerico
    • ScientificPython

    etc. ecc. ma poi questi sono da stupirsi dal momento che sono enormi progetti.

    La funzionalità di riduzione può essere fatto utilizzando la funzione di ricorsione di cui credo di Guido pensiero è stato più esplicito.

    Aggiornamento:

    Dal Google Code Search è stato interrotto il 15-Gen-2012, oltre il ripristino del regolare le ricerche di Google, c’è qualcosa che si chiama Frammenti Di Codice Collezione che sembra promettente. Un certo numero di altre risorse, sono citati nelle risposte a questo (chiuso) domanda Di ricambio per Codice di Google Search?.

    Update 2 (29 Maggio 2017):

    Una buona fonte di esempi in Python (in codice open-source) è il Nullege ricerca motore.

    • “La funzionalità di riduzione può essere fatto utilizzando la funzione di ricorsione” …O un for loop.
    • Inoltre, cercare di ridurre() produce progetti che definiscono ridurre le funzioni all’interno del loro codice. Si dovrebbe cercare lang:python “ridurre(” per trovare la usi la funzione built-in.
    • Osewa: Anche la ricerca di lang:python "reduce(" si trovare definizioni di reduce a seconda del codice sorgente stile di codifica.
  14. 2
    import os
    
    files = [
        # full filenames
        "var/log/apache/errors.log",
        "home/kane/images/avatars/crusader.png",
        "home/jane/documents/diary.txt",
        "home/kane/images/selfie.jpg",
        "var/log/abc.txt",
        "home/kane/.vimrc",
        "home/kane/images/avatars/paladin.png",
    ]
    
    # unfolding of plain filiname list to file-tree
    fs_tree = ({}, # dict of folders
               []) # list of files
    for full_name in files:
        path, fn = os.path.split(full_name)
        reduce(
            # this fucction walks deep into path
            # and creates placeholders for subfolders
            lambda d, k: d[0].setdefault(k,         # walk deep
                                         ({}, [])), # or create subfolder storage
            path.split(os.path.sep),
            fs_tree
        )[1].append(fn)
    
    print fs_tree
    #({'home': (
    #    {'jane': (
    #        {'documents': (
    #           {},
    #           ['diary.txt']
    #        )},
    #        []
    #    ),
    #    'kane': (
    #       {'images': (
    #          {'avatars': (
    #             {},
    #             ['crusader.png',
    #             'paladin.png']
    #          )},
    #          ['selfie.jpg']
    #       )},
    #       ['.vimrc']
    #    )},
    #    []
    #  ),
    #  'var': (
    #     {'log': (
    #         {'apache': (
    #            {},
    #            ['errors.log']
    #         )},
    #         ['abc.txt']
    #     )},
    #     [])
    #},
    #[])
    • Potrebbe forse aggiungere un po ‘ di spiegazione di quello che sta succedendo qui? In caso contrario, l’utilità è davvero evidente a tutti.
  15. 2
    def dump(fname,iterable):
      with open(fname,'w') as f:
        reduce(lambda x, y: f.write(unicode(y,'utf-8')), iterable)
  16. 1

    Ho un vecchio Python attuazione di pipegrep che utilizza ridurre e la presenza del modulo per creare un elenco di file di processo:

    files = []
    files.extend(reduce(lambda x, y: x + y, map(glob.glob, args)))

    Ho trovato a portata di mano al momento, ma in realtà non è necessario, come qualcosa di simile è altrettanto buono, e probabilmente più leggibile

    files = []
    for f in args:
        files.extend(glob.glob(f))
    • Come circa un elenco di comprensione? Questo mi sembra un applicazione perfetta per: files = [glob.glob(f) for f in args]
    • In realtà, @steveha, il tuo esempio, il risultato sarà una lista di liste di espanso gocce, piuttosto che un semplice elenco di tutti gli elementi che soddisfano le gocce, ma si potrebbe usare una list comprehension + somma, come @[Eli Courtwright](#16198) punti.
    • Va bene, hai ragione, mi dispiace. Io ancora non mi piace la combinazione di estendere/ridurre/lambda/mappa molto! Vorrei raccomandare l’importazione di itertools, utilizzando il flatten() ricetta docs.python.org/library/itertools.html, e poi la scrittura: files = flatten(glob.glob(f) for f in args) (E questa volta, ho testato il codice prima di pubblicarlo, e so che questo funziona correttamente).
    • files = chain.from_iterable(imap(iglob, args)) dove chain, imap sono da itertools modulo e glob.iglob è utile se un modello da args può produrre file da diverse directory.
  17. 1

    Diciamo che ci sono alcuni annuale di statistica di dati memorizzati in un elenco di Contatori.
    Vogliamo trovare valori MIN/MAX di ogni mese, tra i vari anni.
    Per esempio, per il mese di gennaio dovrebbe essere 10. E per il mese di febbraio sarebbe 15.
    Abbiamo bisogno di memorizzare i risultati in un nuovo Contatore.

    from collections import Counter
    
    stat2011 = Counter({"January": 12, "February": 20, "March": 50, "April": 70, "May": 15,
               "June": 35, "July": 30, "August": 15, "September": 20, "October": 60,
               "November": 13, "December": 50})
    
    stat2012 = Counter({"January": 36, "February": 15, "March": 50, "April": 10, "May": 90,
               "June": 25, "July": 35, "August": 15, "September": 20, "October": 30,
               "November": 10, "December": 25})
    
    stat2013 = Counter({"January": 10, "February": 60, "March": 90, "April": 10, "May": 80,
               "June": 50, "July": 30, "August": 15, "September": 20, "October": 75,
               "November": 60, "December": 15})
    
    stat_list = [stat2011, stat2012, stat2013]
    
    print reduce(lambda x, y: x & y, stat_list)     # MIN
    print reduce(lambda x, y: x | y, stat_list)     # MAX
  18. 1

    Ho oggetti di rappresentazione di una sorta di sovrapposizione di intervalli (genomica esoni), e ha ridefinito la loro intersezione utilizzando __and__:

    class Exon:
        def __init__(self):
            ...
        def __and__(self,other):
            ...
            length = self.length + other.length  # (e.g.)
            return self.__class__(...length,...)

    Quindi quando ho una collezione di essi (ad esempio, in uno stesso gene), io uso

    intersection = reduce(lambda x,y: x&y, exons)
  19. 1

    Ho appena trovato utile l’utilizzo di reduce: dividere la stringa senza rimuovere il delimitatore. Il codice è interamente a livello di programmazione di Lingua blog. Ecco il codice:

    reduce(lambda acc, elem: acc[:-1] + [acc[-1] + elem] if elem == "\n" else acc + [elem], re.split("(\n)", "a\nb\nc\n"), [])

    Ecco il risultato:

    ['a\n', 'b\n', 'c\n', '']

    Nota che gestisce i casi limite che popolare rispondere in MODO non. Per una spiegazione più approfondita, io sono il reindirizzamento al post originale.

  20. 0

    Utilizzando ridurre() per sapere se un elenco di date consecutive:

    from datetime import date, timedelta
    
    
    def checked(d1, d2):
        """
        We assume the date list is sorted.
        If d2 & d1 are different by 1, everything up to d2 is consecutive, so d2
        can advance to the next reduction.
        If d2 & d1 are not different by 1, returning d1 - 1 for the next reduction
        will guarantee the result produced by reduce() to be something other than
        the last date in the sorted date list.
    
        Definition 1: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider consecutive
        Definition 2: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider not consecutive
    
        """
        #if (d2 - d1).days == 1 or (d2 - d1).days == 0:  # for Definition 1
        if (d2 - d1).days == 1:                          # for Definition 2
            return d2
        else:
            return d1 + timedelta(days=-1)
    
    # datelist = [date(2014, 1, 1), date(2014, 1, 3),
    #             date(2013, 12, 31), date(2013, 12, 30)]
    
    # datelist = [date(2014, 2, 19), date(2014, 2, 19), date(2014, 2, 20),
    #             date(2014, 2, 21), date(2014, 2, 22)]
    
    datelist = [date(2014, 2, 19), date(2014, 2, 21),
                date(2014, 2, 22), date(2014, 2, 20)]
    
    datelist.sort()
    
    if datelist[-1] == reduce(checked, datelist):
        print "dates are consecutive"
    else:
        print "dates are not consecutive"

Lascia un commento