Πώς να συγχωνεύσει δύο λεξικά σε μια ενιαία έκφραση;

ψήφοι
3k

Έχω δύο λεξικά Python, και θέλω να γράψω ένα ενιαίο έκφραση που επιστρέφει αυτά τα δύο λεξικά, συγχωνεύονται. Η update()μέθοδος θα ήταν ό, τι χρειάζομαι, αν επιστρέψει λόγω του αντί τροποποίηση μιας dict επί τόπου.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

Πώς μπορώ να βρω αυτό το τελικό νέας dict στο z, όχι x;

(Για να είμαστε εξαιρετικά σαφείς, το τελευταίο-ένα-κερδίζει συγκρούσεις χειρισμό dict.update()είναι αυτό που ψάχνω, καθώς και.)

Δημοσιεύθηκε 02/09/2008 στις 08:44
πηγή χρήστη
Σε άλλες γλώσσες...                            


56 απαντήσεις

ψήφοι
40
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

Για τα στοιχεία με τα πλήκτρα και στις δύο λεξικά ( «β»), μπορείτε να καθορίσετε ποια καταλήγει στην έξοδο από τη θέση ότι μια τελευταία.

Απαντήθηκε 02/09/2008 στις 08:49
πηγή χρήστη

ψήφοι
1k

Στην περίπτωσή σας, τι μπορείτε να κάνετε είναι:

z = dict(x.items() + y.items())

Αυτό, όπως το θέλετε, βάλτε το τελικό dict σε z, και να κάνει η τιμή για το κλειδί bνα παρακαμφθεί σωστά από το δεύτερο ( yαξία) dict είναι:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

Εάν χρησιμοποιείτε Python 3, είναι μόνο λίγο πιο περίπλοκη. Για να δημιουργήσετε z:

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
Απαντήθηκε 02/09/2008 στις 08:50
πηγή χρήστη

ψήφοι
542

Μία εναλλακτική:

z = x.copy()
z.update(y)
Απαντήθηκε 02/09/2008 στις 14:00
πηγή χρήστη

ψήφοι
269

Μια άλλη, πιο συνοπτική, η επιλογή:

z = dict(x, **y)

Σημείωση : αυτό έχει γίνει μια δημοφιλής απάντηση, αλλά είναι σημαντικό να επισημάνουμε ότι αν yέχει κάποια πλήκτρα μη-string, το γεγονός ότι αυτό λειτουργεί σε όλα είναι η κατάχρηση μιας λεπτομέρειας εφαρμογής CPython, και δεν λειτουργεί σε Python 3, ή σε PyPy, IronPython, ή Jython. Επίσης, Guido δεν είναι ένας ανεμιστήρας . Έτσι, δεν μπορώ να συστήσω αυτή την τεχνική για την προώθηση συμβατό ή πολλαπλή εφαρμογή φορητό κώδικα, το οποίο πραγματικά σημαίνει ότι θα πρέπει να αποφεύγεται εντελώς.

Απαντήθηκε 02/09/2008 στις 16:52
πηγή χρήστη

ψήφοι
85

Ήθελα κάτι παρόμοιο, αλλά με τη δυνατότητα να καθορίσετε τον τρόπο συγχωνεύτηκαν οι τιμές για τα διπλά πλήκτρα, γι 'αυτό hacked αυτό έξω (αλλά δεν το δοκιμάσει σε μεγάλο βαθμό). Προφανώς αυτό δεν είναι μια ενιαία έκφραση, αλλά είναι μια ενιαία κλήση της συνάρτησης.

def merge(d1, d2, merge_fn=lambda x,y:y):
    """
    Merges two dictionaries, non-destructively, combining 
    values on duplicate keys as defined by the optional merge
    function.  The default behavior replaces the values in d1
    with corresponding values in d2.  (There is no other generally
    applicable merge strategy, but often you'll have homogeneous 
    types in your dicts, so specifying a merge technique can be 
    valuable.)

    Examples:

    >>> d1
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1)
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1, lambda x,y: x+y)
    {'a': 2, 'c': 6, 'b': 4}

    """
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge_fn(result[k], v)
        else:
            result[k] = v
    return result
Απαντήθηκε 04/09/2008 στις 20:08
πηγή χρήστη

ψήφοι
165

Αυτό κατά πάσα πιθανότητα δεν θα είναι μια δημοφιλής απάντηση, αλλά είναι σχεδόν βέβαιο ότι δεν θέλετε να το κάνετε αυτό. Αν θέλετε ένα αντίγραφο που είναι μια συγχώνευση, στη συνέχεια, χρησιμοποιήστε αντίγραφο (ή deepcopy , ανάλογα με το τι θέλετε) και στη συνέχεια να ενημερώσετε. Οι δύο γραμμές του κώδικα είναι πολύ πιο ευανάγνωστο - περισσότερο Pythonic - από τη δημιουργία μοναδικής γραμμής .items () + .items (). Ρητή είναι καλύτερη από ό, τι υπονοείται.

Επιπλέον, όταν χρησιμοποιείτε .items () (προ Python 3.0), είστε δημιουργώντας μια νέα λίστα που περιέχει τα στοιχεία από την dict. Αν λεξικά σας είναι μεγάλο, τότε αυτό είναι πάρα πολλά γενικά έξοδα (δύο μεγάλες λίστες που θα πρέπει να απορρίπτονται αμέσως μόλις η νέα dict δημιουργείται). ενημέρωση () μπορεί να λειτουργήσει πιο αποτελεσματικά, επειδή μπορεί να τρέξει μέσα από το δεύτερο dict στοιχείο-προς-στοιχείο.

Από την άποψη του χρόνου :

>>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.52571702003479
>>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.694622993469238
>>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
41.484580039978027

IMO η μικρή επιβράδυνση μεταξύ των δύο πρώτων αξίζει τον κόπο για την αναγνωσιμότητα. Επιπλέον, τα επιχειρήματα λέξη-κλειδί για τη δημιουργία λεξικού προστέθηκε μόνο σε Python 2.3, ενώ αντίγραφο () και ενημέρωση () θα λειτουργήσει σε παλαιότερες εκδόσεις.