У якому випадку я використав би кортеж як ключ словника?


79

Я вивчав різницю між списками та кортежами (на Python). Очевидним є те, що кортежі незмінні (значення не можна змінювати після початкового призначення), тоді як списки можна змінювати.

Речення в статті зрозуміло мене:

В якості ключів словника можуть використовуватися лише незмінні елементи, а отже як ключі можуть використовуватися лише кортежі, а не списки.

Мені важко подумати про ситуацію, коли я хотів би використовувати кортеж як ключ словника. Чи можете ви навести приклад проблеми, коли це було б природним, ефективним, елегантним чи очевидним рішенням?

Редагувати:

Дякую за ваші приклади. Поки я вважаю, що дуже важливим додатком є ​​кешування значень функцій.


2
Ви можете використовувати кортежі, але тільки ті, що мають незмінні елементи. Якщо кортеж містить список (як один з його елементів), такий кортеж не можна використовувати як ключ. Основне правило полягає в тому, що дані (tupple) повинні бути хешируемыми.
pepr

Відповіді:


112

Класичний приклад: Ви хочете зберегти значення точки як кортеж (x, y)


4
Ого. Це дуже правда. Я не можу подумати про будь-який інший спосіб ефективного зберігання значень функції! Якщо ваша функція дуже дорога для оцінки, ви робите це лише один раз і зберігаєте бали для подальшого пошуку. +1! Дякую!
Ескуало

4
Домовились. Крім того, скрізь, де ви обробляєте щось у пам'яті, де ви б використовували складний ключ для обробки одного і того ж у реляційній базі даних.
Джо Мейбл

Зараз я реалізую точно такий же сценарій. Яка ефективність пошуку для пошуку? Це O (1) або O (N)?
shiv

30
salaries = {}
salaries[('John', 'Smith')] = 10000.0
salaries[('John', 'Parker')] = 99999.0

EDIT 1 Звичайно, ви можете це зробити salaries['John Smith'] = whatever, але тоді вам доведеться виконати додаткову роботу, щоб розділити ключ на ім’я та прізвище. Що стосовноpointColor[(x, y, z)] = "red" , тут перевага ключа кортежу є більш помітною.

Я повинен наголосити, що це не найкраща практика. У багатьох випадках вам краще створити спеціальні класи для обробки подібних ситуацій, але Аррієта попросила приклади, які я дав їй (йому).

РЕДАГУВАТИ 0

До речі, кожен кортежний елемент теж повинен бути хешируемым:

>>> d = {}
>>> t = (range(3), range(10, 13))
>>> d[t] = 11
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
>>>

2
Я мало використовую python, але хіба зарплата [('Джон Сміт')] = 99998 не буде дійсним ключем словника?
GrayWizardx

1
Я згоден, що ви можете це зробити, але я б змоделював ці дані із класом Employee з __init __ (self, Firs, Last, Salary) та створив екземпляр для кожного елемента у списку. У цьому випадку використання трюку "кортеж як ключ" здавалося б мені трохи неприродним. Як ти гадаєш?
Ескуало

1
звичайно. Але тоді вам доведеться зробити додаткову роботу, якщо ви хочете розділити ключ, скажімо, на ім’я та прізвище.
Борис Горелік

1
Дякую за ваші редагування, я вважаю, що кольоровий приклад дуже хороший, як dict[tuple] = f(tuple)зазначено у відповідях. Я, до речі, "він" :)
Ескуало,

4
Зверніть увагу, що вам не потрібні дужки, кортежі визначаються комою. salaries['John', 'Smith'] = 10000.0теж спрацює :)
Геретрон,

8

Я використовую кортежі багато часу як dictключовий, наприклад

  • Я їх використовую, коли мені доводиться створювати унікальний ключ із декількох значень, наприклад

    заснований на first_name, last_namekey може бути key = '%s_%s'%(first_name, last_name)але кращий спосіб key = (first_name, last_name)тому, що

    1. Це читабельніше, коротше і менше обчислень
    2. Отримати окремі значення простіше простого
    3. Найголовніше key = '%s_%s'%(first_name, last_name)- це неправильно і може не надавати унікальні ключі для всіх значень first_nameі, last_nameнаприклад, коли значення містять_
  • Кешування результатів функції

    def func(a1, b1):
        if (a1,b1) in cache: return cache[(a1,b1)]
        ...
    

5

Я використовував кортежі як ключові словарі в програмі, яка порівнює мережеві пристрої за географічним розташуванням. Оскільки пристрої називаються однаково для кожного розташування, це забезпечує природний спосіб дізнатись, чи пристрій, що відповідає цьому поєднанню, бачився ще при обробці кратних.

тобто

seen = {}
seen[('abc', 'lax')] = 1
seen[('xyz', 'nyc')] = 1

5

Ви використовуєте кортежі як ключі, коли хочете показати кілька елементів, які утворюють ключ разом.

Наприклад: {(<x-coordinate>,<y-coordinate>): <indicating letter>}

Тут, якщо ми використовуємо x-coordinateабо y-coordinateокремо, ми не будемо представляти цю точку.


5

У контексті машинного навчання та глибокого навчання, якщо ви шукаєте найкращі гіперпараметри , то використання кортежів як ключів, безумовно, надзвичайно корисно.

Припустимо, ви шукаєте найкраще поєднання гіперпараметра для learning_rate, regularization_factorі model_complexity.

Тоді ви можете мати словник на Python, де ви створюєте різну комбінацію, яку ці hparams можуть приймати як ключі, та відповідні їм матриці ваги з алгоритму навчання як значення

hparams_hist = {}
hparams_hist[(0.001, 0.7, 5)] = weight_matrix1
hparams_hist[(0.0001, 0.8, 2)] = weight_matrix2

Ці вагові матриці додатково потрібні для прогнозування в режимі реального часу.


1
Я бачу, що роблю це багато! Чудовий приклад.
ruancomelli


2

Я припускаю, що у випадку сортування може бути корисно використовувати кортеж. Наприклад, припустимо, що ключ словника представляє поле сортування (очевидно, що там буде поле сортування за замовчуванням, щоб запобігти ключуNone ). Якщо вам потрібні кілька полів сортування, наприклад, випадок сортування за прізвищем, то ім’я, чи не буде корисним використання кортежу як ключа словника?

Звичайно, така ідея може мати обмежене використання, але це не означає, що вона абсолютно марна.


2

Ви можете використовувати його для аналізу воронки, якщо ви створюєте базовий інструмент аналітики.

Наприклад , підраховуючи, скільки людей натиснуло зображення3 після наведення курсору на текст2.

    funnels = defaultdict(int)
    funnels[('hovered_text2', 'clicked_image3')] += 1

2

Ви можете використовувати його для приблизно постійного часу пошуку точки в просторі пошуку. Наприклад, ви можете використовувати його для вирішення проблеми задоволення обмежень, де кожен кортеж може містити деякі обмеження. Обмеження може мати вигляд (v1.v2), де color (v1)! = Color (v2) для розмальовки prob і т. Д. Використовуючи кортежі як ключі словника, ви зможете постійно визначити, чи відповідає перестановка обмеженню чи ні .


1
def getHash(word):
    result={}
    for i in range(len(word)):
        if word[i] in result:
            result[word[i]]+=1
        else :
            result[word[i]]=1

    return tuple (sorted((result.items())))


def groupAnagrams(words):
    resultHash={}
    for i in range(len(words)):
        s=getHash(words[i].lower())
        #print s
        if s in resultHash :
            l=list(resultHash[s]) 
            l.append(words[i])
            resultHash[s] = l # list(resultHash[s]).append(words[i])  
        else :
            resultHash[s]=[words[i]] # Creating list 

    return resultHash.values()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.