Porównaj ceny domen i usług IT, sprzedawców z całego świata

Sprawdź, czy wszystkie wartości słownika są równe - gdy wartość jest nieznana


Mam 2 słowniki:
wartości w każdym słowniku

powinien

być równym.


Ale

Nie wiem, co to będzie za numer ...
dict1 = {'xx':A, 'yy':A, 'zz':A}
dict2 = {'xx':B, 'yy':B, 'zz':B}


N.B.

A nie jest równe B.


N.B.

Zarówno A, jak i B są w rzeczywistości ciągami liczb dziesiętnych (np. „-2.304998”), ponieważ zostały wyodrębnione z pliku tekstowego
Chcę utworzyć inny słownik, który skutecznie podsumuje te dane, ale tylko wtedy, gdy wszystkie wartości w każdym słowniku są takie same.

to znaczy
summary = {}
if dict1['xx'] == dict1['yy'] == dict1['zz']:
summary['s'] = dict1['xx']
if dict2['xx'] == dict2['yy'] == dict2['zz']:
summary['hf'] = dict2['xx']

Czy jest na to zgrabny sposób w jednej linii?
Wiem, że można stworzyć słownik ze zrozumieniem
summary = {k:v for (k,v) in zip(iterable1, iterable2)}

ale zmagam się zarówno z podstawą pętli for, jak i instrukcją if ...
Byłbym wdzięczny za porady.
widziałem

to pytanie
https://coderoad.ru/35253971/
ale wszystkie odpowiedzi zdają się polegać na tym, że znają już sprawdzaną wartość (czyli wszystkie wpisy w słowniku są równe znanej liczbie) - chyba, że ​​czegoś mi brakuje.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

set
s to niezawodny sposób, aby przejść tutaj, ale tylko do celów związanych z kodem golfowym tutaj jest wersja, która może obsługiwać wartości dict, które nie są hashowane:
expected_value = next(iter(dict1.values())) # check for an empty dictionary first if that's possible
all_equal = all(value == expected_value for value in dict1.values())

all
kończy działanie wcześnie z powodu niezgodności, ale konstruktor kolekcji jest na tyle dobrze zoptymalizowany, że nie powiedziałbym, że ma to znaczenie bez profilowania na rzeczywistych danych testowych. Główną zaletą tej wersji jest obsługa wartości, których nie można mieszać.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jednym ze sposobów jest użycie
set
. Wiesz, że iteracja
set
ma długość 1, jeśli jest w niej tylko jedna wartość:
if len(set(dct.values())) == 1:
summary[k] = next(iter(dct.values()))

Działa to oczywiście tylko wtedy, gdy wartości słownika są zaszyfrowane.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Chociaż możemy użyć do tego
set
, ma to wiele wad, gdy dane wejściowe są duże. Może zajmować pamięć proporcjonalnie do wielkości sygnału wejściowego i zawsze skanuje cały sygnał wejściowy, nawet jeśli wcześnie zostaną znalezione dwie różne wartości. Ponadto dane wejściowe muszą być hashowane.
Dla 3 klawiszy nie ma to większego znaczenia, ale dla większych, zamiast używać
set
, możemy użyć
itertools.groupby
https://docs.python.org/3/libr ... oupby
i zobacz, czy tworzy wiele grup:
import itertoolsgroups = itertools.groupby(dict1.values())# Consume one group if there is one, then see if there's another.
next(groups, None)
if next(groups, None) is None:
# All values are equal.
do_something()
else:
# Unequal values detected.
do_something_else()
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Z wyjątkiem czytelności, nie obchodzą mnie wszystkie odpowiedzi związane z ustawieniami lub wartościami. Wszyscy

jest zawsze

O (N) w czasie i pamięci. W praktyce może to być szybsze, chociaż zależy to od rozkładu wartości.
Ponadto, ponieważ zestaw używa operacji mieszania, możesz również mieć duży, duży stały mnożnik do swojego narzutu. A twoje wartości muszą być haszowane, gdy test równości jest wszystkim, czego potrzeba.

W teorii

lepiej jest wziąć pierwszą wartość ze słownika i poszukać pierwszego przykładu w pozostałych wartościach, które nie są równe.

zestaw

może być szybszy niż poniższe rozwiązanie, ponieważ jego pracę można sprowadzić do implementacji w C.
def all_values_equal(d):
if len(d)<=1: return True # Treat len0 len1 as all equal
i = d.itervalues()
firstval = i.next()
try:
# Incrementally generate all values not equal to firstval
# .next raises StopIteration if empty.
(j for j in i if j!=firstval).next()
return False
except StopIteration:
return Trueprint all_values_equal({1:0, 2:1, 3:0, 4:0, 5:0}) # False
print all_values_equal({1:0, 2:0, 3:0, 4:0, 5:0}) # True
print all_values_equal({1:"A", 2:"B", 3:"A", 4:"A", 5:"A"}) # False
print all_values_equal({1:"A", 2:"A", 3:"A", 4:"A", 5:"A"}) # True

W powyższym przypadku:
(j for j in i if j!=firstval)

równoważny:
def gen_neq(i, val):
"""
Give me the values of iterator i that are not equal to val
"""
for j in i:
if j!=val:
yield j
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Znalazłem to rozwiązanie, które znajduję całkiem sporo Połączyłem inne rozwiązanie znalezione tutaj:

Wpisz tutaj opis linku
https://coderoad.ru/42880043/
user_min = {'test':1,'test2':2}
all(value == list(user_min.values())[0] for value in user_min.values())>>> user_min = {'test':1,'test2':2}
>>> all(value == list(user_min.values())[0] for value in user_min.values())
False
>>> user_min = {'test':2,'test2':2}
>>> all(value == list(user_min.values())[0] for value in user_min.values())
True
>>> user_min = {'test':'A','test2':'B'}
>>> all(value == list(user_min.values())[0] for value in user_min.values())
False
>>> user_min = {'test':'A','test2':'A'}
>>> all(value == list(user_min.values())[0] for value in user_min.values())
True

Ok dla małego słownictwa, ale nie jestem pewien co do dużego słownictwa, ponieważ otrzymujemy wszystkie wartości, aby wybrać pierwszą

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się