Назовите структуру словаря, в которой ключи хранятся в предсказуемом порядке?

Примечание. Хотя мой конкретный контекст - Objective-C, мой вопрос на самом деле выходит за рамки выбора языка программирования. Кроме того, я пометил это как «субъективное», поскольку кто-то обязательно будет жаловаться в противном случае, но я лично считаю, что это почти полностью объективно. Кроме того, я знаю этот связанный вопрос SO, но поскольку это была более серьезная проблема , Я подумал, что лучше сделать это отдельным вопросом. Пожалуйста, не критикуйте вопрос, не прочитав и не поняв его полностью. Спасибо!

Большинство из нас знакомы с словарь абстрактный тип данных, в котором хранятся ассоциации "ключ-значение", независимо от того, назовем ли мы его картой, словарем, ассоциативным массивом, хешем и т. д., в зависимости от выбранного нами языка. Простое определение словаря можно резюмировать тремя свойствами:

  1. Доступ к значениям осуществляется по ключу (а не по индексу, как массив).
  2. Каждый ключ связан со значением.
  3. Каждый ключ должен быть уникальным.

Любые другие свойства, возможно, являются удобствами или специализацией для определенной цели. Например, некоторые языки (особенно языки сценариев, такие как PHP и Python) стирают границу между словарями и массивами и обеспечивают упорядочение словарей. Каким бы полезным это ни было, такие дополнения не являются фундаментальной характеристикой словаря. В чистом смысле фактические детали реализации словаря не имеют значения.

Что касается моего вопроса, наиболее важным наблюдением является то, что порядок перечисления ключей не определен - словарь может предоставлять ключи в любом порядке, который он считает наиболее удобным, и заказчик должен организовать их по желанию.

Я создал пользовательские словари, которые устанавливают определенный порядок клавиш, включая естественный порядок сортировки (на основе сравнения объектов) и порядок вставки. Очевидно, первое можно назвать некоторым вариантом в SortedDictionary (который я фактически уже реализовал), но последний более проблематичен. Я видел LinkedHashMap и LinkedMap (Java), OrderedDictionary (.NET), OrderedDictionary (Flash), OrderedDict (Python) и OrderedDictionary (Objective-C). Некоторые из них более зрелые, некоторые - более обоснованные.

LinkedHashMap назван в соответствии с реализацией в традициях Java-коллекций: «связанный», потому что он использует двусвязный список для отслеживания порядка вставки, и «хэш», потому что он является подклассом HashMap. Помимо того факта, что пользователю не следует об этом беспокоиться, имя класса на самом деле даже не указывает на то, что он делает. Использование упорядоченного похоже на консенсус среди существующего кода, но поиск в Интернете по этой теме также выявил понятную путаницу между «упорядоченным» и «отсортированным», и я чувствую то же самое. В реализации .NET даже есть комментарий о явном неправильном названии и предлагается вместо этого использовать «IndexedDictionary», поскольку вы можете извлекать и вставлять объекты в определенный момент в упорядочивании.

Я разрабатываю фреймворк и API и хочу назвать класс как можно более разумным. С моей точки зрения, проиндексированный, вероятно, будет работать (в зависимости от того, как люди его интерпретируют и на основе заявленной функциональности словаря), упорядоченный неточен и имеет слишком большой потенциал для путаница, и ссылка "сразу вышла" (извинения перед Монти Пайтон). ;-)

Какое имя будет для вас наиболее понятным для пользователя? Есть ли конкретное имя, которое точно описывает, что делает класс? (Я не прочь использовать несколько более длинные имена, например InsertionOrderDictionary, если это необходимо.)

Изменить: Еще одна серьезная возможность (обсуждаемая в моем ответе ниже) - IndexedDictionary. Мне не очень нравится «порядок вставки», потому что он не имеет смысла, если вы позволяете пользователю вставлять ключи по определенному индексу, менять их порядок и т. Д.


person Quinn Taylor    schedule 20.06.2009    source источник
comment
+1 за замечательный вопрос. К сожалению, общепринятого значения нет. У людей есть свой выбор. В .NET интерфейс для отсортированного перечислимого называется IOrderedEnumerable. На самом деле это даже не согласовано в .NET. Порядок вставки, соответствующий словарю, называется OrderedDictionary. Дэвид М. Кин, инсайдер из MS, сказал, что это неправильное название, и IndexedDictionary подходит лучше. Лучше выбрать то, что более широко принято в объективном мире.   -  person nawfal    schedule 21.05.2014


Ответы (9)


Я голосую за OrderedDictionary по следующим причинам:

«Индексированный» никогда не используется в классах Какао, за исключением одного экземпляра. Он всегда появляется как существительное (NSIndexSet, NSIndexPath, objectAtIndex: и т. Д.). Есть только один случай, когда "Index" появляется как глагол, который находится в свойстве "indexed" NSPropertyDescription: isIndexed и setIndexed. NSPropertyDescription примерно аналогичен столбцу таблицы в базе данных, где «индексирование» означает оптимизацию для ускорения поиска. Следовательно, имеет смысл, если NSPropertyDescription является частью структуры Core Data, что «isIndexed» и «setIndexed» будут эквивалентны индексу в базе данных SQL. Поэтому называть его «IndexedDictionary» было бы излишним, поскольку индексы в базах данных создаются для ускорения времени поиска, но словарь уже имеет время поиска O (1). Однако называть его «IndexDictionary» также было бы неправильно, поскольку «индекс» в Какао относится к позиции, а не к порядку. Эти два семантически различны.

Я понимаю вашу озабоченность по поводу "OrderedDictionary", но прецедент уже создан в Какао. Когда пользователи хотят поддерживать определенную последовательность, они используют «упорядоченные»: - [NSApplication orderDocuments], - [NSWindow OrderedIndex], - [NSApplicationhibitedWindows] и т. Д. Итак, Джон Пири в основном прав.

Однако вы не хотите, чтобы вставка в словарь была обузой для ваших пользователей. Они захотят создать словарь один раз, а затем поддерживать в нем соответствующий порядок. Они даже не захотят запрашивать объекты в определенном порядке. Спецификация заказа должна быть сделана во время инициализации.

Поэтому я рекомендую сделать OrderedDictonary кластером классов с частными подклассами InsertionOrderDictionary, NaturalOrderDictionary и CustomOrderDictionary. Затем пользователь просто создает OrderedDictionary следующим образом:

OrderedDictionary * dict = [[OrderedDictionary alloc] initWithOrder:kInsertionOrder];
//or kNaturalOrder, etc

Для CustomOrderDictionary вы можете попросить их предоставить вам селектор сравнения или даже (если они работают с 10.6) блок. Я думаю, что это обеспечит максимальную гибкость для будущего расширения, сохранив при этом подходящее имя.

person Dave DeLong    schedule 30.06.2009
comment
Я уже обсуждал с Дейвом ранее, что CoreData, возможно, не строго является фреймворком Cocoa. Мне нравится логика Дэйва, но я действительно не решаюсь представить свой собственный кластер классов только для заказа. Я хотел бы предоставить гибкую функциональность с минимальной сложностью. Мне кажется, что в этом случае частный кластер классов скрывает слишком много деталей - цель кластера классов состоит в том, чтобы скрыть варианты реализации, а не в поведении. Вы не могли посмотреть на OrderedDictonary и знать, в каком порядке будут перечислены ключи. Для меня это явный недостаток дизайна. - person Quinn Taylor; 30.06.2009
comment
Вы делаете много замечаний по поводу прецедента заказа в Какао, хотя я все еще не согласен со всем, начиная с «Однако». :-) Любое автоматическое настраиваемое упорядочение будет подпадать под будущее расширение SortedDictionary путем указания NSSortDescriptor, настраиваемого селектора и т. Д. Нет необходимости создавать особый вид SortedDictionary для каждого желаемого порядка сортировки. Хотя мне до некоторой степени нравится индексирование, согласие с существующими реализациями (на других языках) и соглашениями о Какао превосходит личное мнение. Спасибо! - person Quinn Taylor; 06.07.2009

Голосую за InsertionOrderDictionary. Ты сделал это.

person John Kugelman    schedule 20.06.2009
comment
Даже если бы InsertionOrderDictionary был идеально описательным названием для этой концепции ... девять слогов для библиотечного класса заставили меня съежиться. - person ; 28.06.2009

Решительное голосование за OrderedDictionary.

Слово «заказанный» означает именно то, что вы рекламируете: при итерации по списку элементов существует определенный порядок их выбора. «Индексированный» - это слово реализации - оно больше говорит о том, как достигается упорядочение. Индекс, связанный список, дерево ... пользователю все равно; этот аспект структуры данных должен быть скрыт. «Заказанный» - это точное слово для дополнительной функции, которую вы предлагаете, независимо от того, как вы это делаете.

Кроме того, похоже, что выбор порядка может быть на усмотрение пользователя. Есть ли причина, по которой вы не могли создать для своего типа данных методы, которые позволяют пользователю переключаться, скажем, с алфавитного порядка на порядок вставки? В случае по умолчанию пользователь выберет конкретный порядок и придерживается его, и в этом случае реализация будет не менее эффективной, чем если бы вы создали специализированные подклассы для каждого метода упорядочивания. А в некоторых менее используемых случаях разработчик может фактически пожелать использовать любой из множества различных порядков для одних и тех же данных, в зависимости от контекста приложения. (Я могу вспомнить конкретные проекты, над которыми я работал, где мне хотелось бы иметь такую ​​структуру данных.)

Назовите это OrderedDictionary, потому что это именно то, что вам нужно. (Честно говоря, у меня больше проблем с использованием слова «Словарь», потому что это слово в значительной степени подразумевает упорядочение, в то время как популярные реализации такого рода не обеспечивают его, но это моя любимая мозоль. Вы действительно должны просто иметь возможность скажите «Словарь» и знайте, что упорядочение происходит в алфавитном порядке - потому что это то, что такое словарь - но этот аргумент слишком поздно для существующих реализаций на популярных языках.) И позвольте пользователю получить доступ в том порядке, в котором он выбирает.

person Community    schedule 27.06.2009
comment
Я понимаю вашу точку зрения, но не согласен с тем, что индекс - это слово реализации - я согласен с другими и сказал бы, что этот массив тоже. Индекс подразумевает произвольный доступ, который поддерживает мой словарь; то есть пользователь может напрямую обращаться к клавишам от 0 до n-1. Я все еще думаю, что на мой вкус упорядоченный слишком близок к сортировке - это означает, что структура (а не пользователь) упорядочивает элементы. Возможна смена порядка, но у меня уже есть SortedDictionary, который вызывает -compare: для каждого элемента для определения порядка. Это также добавляет ненужной сложности. Все, что имеет несколько порядков, должно использовать композицию. - person Quinn Taylor; 27.06.2009
comment
У вас также есть очень веская точка зрения о словаре по сравнению с таким термином, как карта. Ах, ошибки истории. Даже в этом случае, если вы думаете об отношении термин-определение, это все равно имеет смысл. (Можно сказать, что словарь почти подразумевает множественную карту, поскольку может быть несколько определений.) Тем не менее, я считаю, что словарь предпочтительнее ассоциативного массива (PHP) или простого хэша (спасибо, Ruby). Также имейте в виду, что Objective-C и Какао действительно используют некоторые соглашения, характерные для языка. Кроме того, Objective-C поддерживает динамическое добавление методов через категории, поэтому пользователи могут добавлять свои собственные конкретные порядки. - person Quinn Taylor; 27.06.2009
comment
Думаю, я часто думаю о чем-то вроде Десятичной системы Дьюи, когда думаю об индексе (не связанном с compsci): системе классификации, которая, прежде всего, обеспечивает быстрый доступ, больше, чем определение того, лучше ли одна книга или предшествует другой книге. Где, когда вы определяете предшествующее отношение между вашими ключами. Но я тоже понимаю вашу точку зрения - и, конечно же, согласен с тем, что индексирование намного лучше, чем что-то вроде ассоциативного массива (ага). - person ; 28.06.2009

С момента публикации этого вопроса я начинаю склоняться к чему-то вроде IndexedDictionary или IndexableDictionary. Хотя полезно иметь возможность поддерживать произвольный порядок ключей, ограничение его только порядком вставки кажется ненужным ограничением. Кроме того, мой класс уже поддерживает indexOfKey: и keyAtIndex:, которые (намеренно) аналогичны indexOfObject: и objectAtIndex: NSArray. Я настоятельно подумываю добавить insertObject:forKey:atIndex:, который соответствует с insertObject:atIndex: NSMutableArray.

Всем известно, что вставка в середину массива неэффективна, но это не значит, что нам нельзя позволять делать это в тех редких случаях, когда это действительно полезно. (Кроме того, реализация могла бы тайно использовать двусвязный список или любую другую подходящую структуру для отслеживания порядка, если это необходимо ...)

Большой вопрос: является ли «индексируемый» или «индексируемый» таким же расплывчатым или потенциально запутанным, как «упорядоченный»? Подумают ли люди об указателях баз данных, указателях книг и т. Д.? Будет ли вредно, если они предположат, что это реализовано с помощью массива, или это может упростить понимание пользователем функциональности?


Изменить: это имя имеет еще больше смысла, учитывая тот факт, что я рассматриваю возможность добавления методов, которые работают с NSIndexSet в будущем. (NSArray имеет _ 7_, а также методы добавления / удаления наблюдателей для объектов по заданным индексам.)

person Quinn Taylor    schedule 20.06.2009
comment
Я думаю, что индексирование предпочтительнее индексируемого. Это больше похоже на то, как вещи обычно называются в Какао (например, NSAttributedString, а не NSAttributableString). Мне нравится IndexedDictionary. - person Chuck; 21.06.2009
comment
я думаю, что индекс слишком сильно связан с базами данных и эффективным поиском. Если бы я услышал "О, это индексированный словарь, я бы подумал" Индексированный? " Чем? Ценность? Действительно быстрый поиск ключей? и т. д. и т. д. - person Richard Levasseur; 22.06.2009
comment
Что забавно, потому что я как бы принадлежу к противоположному лагерю, где я сильнее всего ассоциирую индекс с массивами. Как ни странно, в этом случае индекс на самом деле связан с действительно быстрым поиском ключа. ;-) В любом случае, должным образом отмечено, и спасибо за отзыв! - person Quinn Taylor; 22.06.2009
comment
В контексте Какао индекс всегда используется в смысле местоположения в упорядоченной коллекции. - person Chuck; 23.06.2009
comment
Одним из прискорбных недостатков этого имени является то, что подряд звуки d смешиваются друг с другом, поэтому (например) NSIndexedDictionary в конечном итоге звучит как NSIndexDictionary и имеет вводящее в заблуждение сходство с NSIndexSet, что совершенно не связано. Хотя OrderedDictionary звучит как OrderDictionary, это не приведет к такой же путанице с существующими классами Какао. К тому же «заказанный» немного легче сказать, чем проиндексированный. Прокляните наш ленивый язык и повторяющиеся твердые согласные !! ;-) - person Quinn Taylor; 05.08.2009

А как насчет KeyedArray?

person Chris Suter    schedule 22.06.2009
comment
Хм, проблема в том, что это, по сути, словарь, а не массив. (Фактически, структура, которая организует ключ, даже не обязательно должна быть массивом - связанный список тоже хорошо работает.) Тем не менее, я ценю ввод! :-) - person Quinn Taylor; 22.06.2009
comment
Проголосовали ради этого. Ты тоже прав. @QuinnTaylor, хотя я согласен, что массив сбивает с толку, Крис считает семантическую точку зрения, а не точку реализации. В .NET есть KeyedCollection, который ясно передает идею о том, что это такое. Звучит как коллекция, соблюдающая порядок, но также поддерживает ключевые индексы. - person nawfal; 21.05.2014

Как вы сказали в последнем абзаце, я думаю, что InsertionOrder (ed) Dict (ionary) довольно однозначен; Я не понимаю, как это можно интерпретировать иначе, как то, что ключи будут возвращены в том порядке, в котором они были вставлены.

person Mark Rushakoff    schedule 20.06.2009

Разве отсоединение индексированного порядка от порядка вставки не сводится просто к хранению массива и словаря в одном объекте? Думаю, мой голос за этот тип объекта - IndexedKeyDictionary

In C#:

public class IndexedKeyDictionary<TKey, TValue> { 

  List<TKey> _keys;
  Dictionary<TKey, TValue> _dictionary;
  ...

  public GetValueAtIndex(int index) {
    return _dictionary[_keys[index]];
  }

  public Insert(TKey key, TValue val, int index) {
    _dictionary.Add(key, val);

    // do some array massaging (splice, etc.) to fit the new key
    _keys[index] = key;
  }

  public SwapKeyIndexes(TKey k1, TKey k2) {
    // swap the indexes of k1 and k2, assuming they exist in _keys
  }
}

Что было бы действительно круто, так это индексированные значения ... так что у нас есть способ отсортировать значения и получить новый порядок ключей. Например, если бы значения были координатами графика, и мы могли бы читать ключи (имена бункеров), когда мы перемещаемся вверх / вниз по координатной плоскости. Как бы вы назвали эту структуру данных? IndexedValueDictionary?

person Jeff Meatball Yang    schedule 22.06.2009
comment
Что ж, это может сводиться к простой композиции объектов, да - детали менее актуальны (хотя это не сработает как есть для моих нужд). Чтобы сделать то, что вы предлагаете, NSDictionary (в Какао) уже имеет метод под названием keysSortedByValueUsingSelector:, который я наследую бесплатно, где селектор - это имя метода, вызываемого для каждого значения для их сравнения. Это не поддерживает значения в заданном порядке в самом словаре, но позволяет сортировать их, как вам нравится, по запросу, что, вероятно, полностью достаточно почти для всех случаев. - person Quinn Taylor; 22.06.2009

На первый взгляд, я получил первый ответ - InsertionOrderDictionary, хотя это немного неоднозначно относительно того, что на первый взгляд означает InsertionOrder.

То, что вы описываете, звучит для меня почти так же, как карта C ++ STL. Насколько я понимаю, карта - это словарь, в котором есть дополнительные правила, включая порядок. STL просто называет это «картой», что, на мой взгляд, вполне уместно. Уловка с картой заключается в том, что вы не можете отдать должное наследованию, не сделав его избыточным, то есть "MapDictionary". Это слишком избыточно. «Карта» слишком проста и оставляет много места для неправильного толкования.

Хотя "CHMap" может быть неплохим выбором после просмотра ссылки на вашу документацию.

Может, "CHMappedDictionary"? знак равно

Удачи.

Изменить: Спасибо за разъяснения, каждый день вы узнаете что-то новое. знак равно

person slycrel    schedule 21.06.2009
comment
На самом деле карты и словари - это одно и то же, как я уже упоминал в первой части своего поста. (К сожалению, C ++ добавил упорядочение и по-прежнему называет его картой, вероятно, для краткости, но это вызывает путаницу в таких случаях, как ваш.) Таким образом, любая комбинация карты и словаря автоматически избыточна и, следовательно, не является хорошим названием. Однако я не могу сказать, что согласен с тем, что порядок размещения расплывчатый. Люди, кажется, это понимают, хотя я думаю, что эта терминология слишком специфична для того, что поддерживает структура. : - / - person Quinn Taylor; 23.06.2009

Единственная разница в том, что allKeys возвращает ключи в определенном порядке? Если так, я бы просто добавил методы allKeysSorted и allKeysOrderdByInsertion в стандартный NSDictionary API.

Какова цель этого словаря порядка размещения? Какие преимущества он дает программисту по сравнению с массивом?

person Steven Canfield    schedule 20.06.2009
comment
Нет, это не единственная разница. Я хочу постоянно отслеживать порядок ключей, а не просто создавать массив, когда пользователь запрашивает все ключи. Настоящая проблема с добавлением методов в NSDictionary (я полагаю, через категорию) заключается в том, что вы не можете добавлять ivars, поэтому это невозможно. Не забывайте, что -allKeys вызывает -keyEnumerator (примитив NSDictionary), и это, как правило, более эффективный способ перечисления ключей в любом случае. - person Quinn Taylor; 20.06.2009
comment
Преимущество для программистов состоит в том, что они могут сохранять вещи в словаре по ключам, как обычно, но также могут вспоминать порядок, в котором были добавлены вещи. Это может быть полезно для обработки содержимого словаря в определенном порядке, когда очередь не нужна или не совсем то, что вам нужно. Другое использование может быть адаптировано из LinkedHashMap Java - вы можете указать, что при доступе к ключам или их повторной вставке они должны перемещаться в конец списка. (Это неэффективно, поскольку требует линейного поиска, но позволяет такие вещи, как удаление наименее недавно использованных элементов из кеша.) - person Quinn Taylor; 20.06.2009