- 1
- 2
- 3
- 4
- 5
- 6
- 7
import json
a = {}
b = {}
for i in xrange(128): a[str(i)] = i
for i in a: b[i] = a[i]
print a == b
print json.dumps(a) == json.dumps(b)
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
0
import json
a = {}
b = {}
for i in xrange(128): a[str(i)] = i
for i in a: b[i] = a[i]
print a == b
print json.dumps(a) == json.dumps(b)
Результат:
True
False
Почему не True True ?
Fike # 0
а) питух дерьмо
б) for i in xrange и i in a не гарантируют одинаковый порядок ключей
в) на сравнение словарей это влияет, а вот на сравнение строк еще как
г) возвращаемся к тому, что питух дерьмо, ибо мапа не должна зависеть от порядка объявления ключей
д) сам-то принт чего не сделаешь да не посмотришь
gost # 0
bormand # 0 ⇈
Лучше бы отсортировали по алфавиту. Кому нахуй нужен этот порядок добавления?
Я вот в другом порядке вторую мапу набью. И она будет равна первой т.к. при сравнении порядок не играет роли. А json представление у них будет разное т.к. порядок обхода разный. Т.е. тройка не решает эту проблему.
З.Ы. А решить эту проблему можно только сортировкой перед сериализацией в жсон. Почти как DER в ASN.1
gost # 0 ⇈
Какую проблему-то? В «Питоне» «JSON» — это просто строка, о её внутренностях «Питон» ничего не знает и знать не должен. Никакой проблемы в этом нет.
Вот если бы он словари сравнивал порядкозависимо, тогда да, был бы багор.
bormand # 0 ⇈
Т.е. в терминах ASN.1 это аналог BER но не DER.
Desktop # 0 ⇈
- зачем? зачем?
bormand # 0 ⇈
Хотя, в json, конечно, из-за пробелов и переносов строк все полимеры будут просраны. Всё-таки в двоичных форматах единства представления легче добиться.
Desktop # 0 ⇈
Чисто для сравнения двух джейсонов?
gost # 0 ⇈
Это-то как раз не проблема, достаточно просто не ставить никакие пробелы и переносы строк. А вот что меня беспокоит — так это представление плавающих питухов. Можно ли гарантировать, что один и тот же питух будет сериализован в одну и ту же строку на любом компьютере?
Desktop # 0 ⇈
bormand # 0 ⇈
Надо тестить старые сборки питона или сборки под другие платформы. Вот там могут быть отличия.
Desktop # 0 ⇈
Я думал, надо проверять разные языки и сериализаторы
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
На своём проверил, осталось проверить все остальные:
bormand # 0 ⇈
Для всех остальных чисел. А то вдруг ты просто удачное число выбрал.
gost # 0 ⇈
Desktop # 0 ⇈
-
Какой багор)))
gost # 0 ⇈
Desktop # 0 ⇈
Если сделать из дабла строку при помощи интерполяции, то там всё будет окей.
bormand # 0 ⇈
MAKAKA # 0 ⇈
А как ее всякие говны выводят -- пофиг же
Desktop # 0 ⇈
MAKAKA # 0 ⇈
Достаточно сказать "в кроссплатформенном формате JSON индеец имеет такое вот направление"
Desktop # 0 ⇈
Во-вторых, JSON это человекочитаемый формат.
Потому сериализовывать нужно в простые дроби.
MAKAKA # 0 ⇈
>человекочитаемый
а, ну тогда вам шашечки, или ехать?
Или у нас человекочитаемый формат, или ieee-754.
Имхо, для передачи данных между программами человекочитаемый формат не нужен.
Desktop # 0 ⇈
Осилили же как-то printf'ы и прочие логи с выводом плавучки без потери точности.
MAKAKA # 0 ⇈
Desktop # 0 ⇈
Десериализация в следующем номере или по короткому номеру
MAKAKA # 0 ⇈
* Сериализовать питуха так, чтобы его мог понять человек
* Сериализовать питуха так, чтобы его мог понять компутер.
Человек -- существо слабое, и нет большой беды в том, что часть точности питуха проебется.
Тут можно сделать printf из любого практически языка программирования.
Компьютеру же хочется получить питуха точь-в-точь таким, каким его закодировали на той стороне (разумеется, если софт и хард поддерживают питухов такого размера).
Обидно будет узнать, что я передал сообщение по цепочке от компа A к компу B, а оттуда к компу C, и с каждым шагом в нем менялся питух.
Это как с аналоговой пленочной аудиокассетой: чем больше раз переписал песню -- тем она хуёвее.
Так быть не должно.
К сожалению, нужный компьютеру питух человеку не читаем.
Потому можно ввести два вида питуха:
unskillable-petuh: для человека
tsar-petuh aka strict-petuh: для компа. В Hex.
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
Desktop # 0 ⇈
guest # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
Типа пишешь 0.1 а получаешь 0.99999999 или 0.100000001. Потому что между ними более подходящих чисел во флоате нет.
Desktop # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
Desktop # 0 ⇈
Если у нас мантисса на 4 бита, то туда поместится 16 значений, а это всего два порядка в десятичной.
Но у меня с переводами между системами немного всё проржавело, могу и хуйню написать ненароком.
bormand # 0 ⇈
З.Ы. Хотя, наверное, можно округлить в нужную сторону чтобы потом при обратном преобразовании звёзды сошлись... Но это уже не "без потерь", а просто "обратимо несмотря на погрешность".
MAKAKA # 0 ⇈
1111 -- 15
Потому, что это будет так же нечитаемо, как 0xF?
bormand # 0 ⇈
MAKAKA # 0 ⇈
bormand # 0 ⇈
Реально без потерь они означают 0.625, 0.750 и 0.875.
Но у нас битов даже на один десятичный разряд не набирается, поэтому мы смело можем их округлить до 0.6, 0.8 и 0.9. Ну и когда мы будем их переводить обратно в двоичное, то получим то что и было на входе.
Т.е. вроде и обратимо, но 0.101 (2) это нихуя не 0.6. Хотя и рядом.
Видимо вот такой приём и подразумевается как "вывод без потерь точности".
bormand # 0 ⇈
Ну или двоичные дроби. Впрочем ни то ни другое неюзабельно для человека.
Вот будет там какое-нибудь 1609/512 и ты даже не подумаешь, что это кусок пи.
Desktop # 0 ⇈
И Пи я узнаю из 3.14блабла, да. А вот там какую-нибудь постоянную Планка уже фиг, а потому какая мне разница, какая там дробь?
bormand # 0 ⇈
MAKAKA # 0 ⇈
Хочешь кексом, хочешь базой64, хочешь чем хочешь.
Про читаемость https://govnokod.ru/26782#comment556851
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
Именно поэтому я за кресты, где всё просто и понятно: есть отсортированная мапа и есть неотсортированная мапа, в обоих случаях всем похуй на порядок добавления.
З.Ы. В питоне отсортированной мапы, кстати, нету.
MAKAKA # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
В «PEP 468» это сделали для того, чтобы сохранить порядок аргументов в **kwargs: https://www.python.org/dev/peps/pep-0468/#id6.
А вообще, «dict» — это хэш-массив, его ключи совершенно не обязаны быть сравнимыми/сортируемыми.
bormand # 0 ⇈
guest # 0 ⇈
https://mail.python.org/pipermail/python-dev/2012-December/123105.html
Питушня какая-то кмк.
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
В пхп вроде тоже есть.
guest # 0 ⇈
First, the keys that are integer indices (what these are is explained later), in ascending numeric order.
Then, all other string keys, in the order in which they were added to the object.
Lastly, all symbol keys, in the order in which they were added to the object.
про пых не зна
bormand # 0 ⇈
gost # 0 ⇈
https://govnokod.ru/26415#comment524714
gost # 0 ⇈
guest # 0 ⇈
Строка, введенная пользователем, равна другой строке, введеной пользователем. А символ не равен
guest # 0 ⇈
фу! руби!
https://ruby-doc.org/core-2.7.0/Hash.html
Hashes enumerate their values in the order that the corresponding keys were inserted.
Пишут, что since 1.9.
Кто вообще еще не гарантирует это говно из скриптоговна? lua и perl?
Fike # 0 ⇈
gost # 0 ⇈
guest # 0 ⇈
то-есть если я сортирну их явно перед выводом, то все будет тормозить?
не надо только мне рассказывать, что они не сравниваемые: печатаются строки, а строки можно сравнивать.
>* mapping semantic names to column order in a CSV
эм.. типа поменял сигнатуру функции, и поменялся аутпут?
>>* serialising attributes and elements in particular orders in XML
Это единственное, что ладно. Но почему тогда явно не заказать ordereddict?
>Mock objects.
>Alternate namedtuple() where defaults can be specified.
Тим Тоуди, дружище!
В общем ладно, похуй.
Вряд-ли Insertion order станет боттлнеком в скриптоговне, пусть будет
gost # 0 ⇈
Так смысл не в том, чтобы их отсортировать, смысл в том, чтобы показать их в том порядке, в каком они были переданы в функцию.
> Но почему тогда явно не заказать ordereddict?
Потому что тогда тебе придётся вместо простого «f(a=1, b=2, c=3)» писать питушарское «f(OrderedDict((a, 1), (b, 2), (c, 3)))» (не знаю, какой там точно у него коньструктор, мог наврать).
Мне, в общем-то, наиболее полезным показался последний пример, с «Specifying argument priority by order».
guest # 0 ⇈
Мне сложно придумать юзкейс, когда мне это важно, но я могу не уметь мыслить как питониста.
>Потому что тогда тебе придётся вместо простого «f(a=1, b=2, c=3)» писать питушарское
Почему не сделать это при объвлении?
>Specifying argument priority by order
типа я передал foo и bar, и foo важнее, потому что первый?
Мне кажется, что семантика мутновата, хотя может и быть полезно
gost # 0 ⇈
«kwargs» — это просто название аргумента, оно может быть любым. То, что в этот аргумент складываются именованные параметры, определяют две звёздочки перед нем. В пепе, в разделе альтернатив, есть предложение расширить синтаксис тремя звёздочками, но это, очевидно, хуёвая идея. «New syntax is only added to Python under the most dire circumstances».
guest # 0 ⇈
Важно, что:
* я, как автор функции, прошу питона сохранить порядок
* вызывающей стороне пофиг на это
gost # 0 ⇈
Для этого разработчикам «Питона» придётся расширить синтаксис, а это — плохая идея. К расширению синтаксиса следует прибегать только в самых печальных обстоятельствах, когда без этого будет совсем уж говно.
guest # 0 ⇈
я за перл: там порядок в хеше не гарантирован никогда)
вообще есть три кейса
* сохранять порядок вставки
* сортировать по ключу
* не гарантировать порядок
чем один лучше другого?
gost # 0 ⇈
https://www.python.org/dev/peps/pep-0468/#id6
> есть три кейса
Два кейса. Сортировать по ключу нельзя, потому что ключи не обязаны быть сравнимыми. Собственно, они не обязаны даже быть одного типа. А между «сохранять порядок вставки» и «не сохранять порядок вставки» выбор, при прочих равных, очевиден: чем меньше в языке неопределённости, тем лучше.
nemyx # 0 ⇈
https://www.php.net/manual/ru/function.ksort.php
Есть даже krsort, которая сортирует по убыванию ключей. И даже есть uksort, которой ты можешь подсунуть свой компаратор:
https://www.php.net/manual/ru/function.uksort.php
Именно поэтому я за «PHP».
guest # 0 ⇈
зачем давать такую гарантию, которая редко кому нужна
Ты может и для сета хочешь сохранять порядок?
gost # 0 ⇈
А дали такую гарантию после того, как в «CPython» изменили реализацию словаря на такую, которая гарантировала сохранение порядка вставки. И она оказалась быстрее, чем старая.
> Ты может и для сета хочешь сохранять порядок?
А такой сет вполне можно эмулировать имеющимся словарём, причём с сохранением всех асимптот.
guest # 0 ⇈
Хеш, разумеется, может совпадать.
Далее, ты пихаешь их в дерево по хешу, за логарифм находишь нужную корзиночку, и все объекты там проверяешь. Правда, перестройка дерева операция не дешевая.
>когда можно сделать амортизированное царское O(1)?
А как можно получить O(1) для случайного ключа не засрав всю память?
>И она оказалась быстрее, чем старая.
Кажется, что не всегда)
https://bugs.python.org/msg275587
gost # 0 ⇈
А зачем? Ты получишь поиск за питушарские O(logN), при этом тебе ещё и хэш нужно вычислять.
> А как можно получить O(1) для случайного ключа не засрав всю память?
https://en.wikipedia.org/wiki/Hash_table
Вкратце: вспоминаем Царя, берём МАССИВ buckets на N элементов-списков, берём нормированный в [0; N) (банальным %, например) хэш H ключа, добавляем в buckets[H] пару (ключ, значение) — как ты и предлагал.
Теперь, если у нас достаточно хороший хэш и достаточно малая заполненность таблицы (отношение суммарного количества элементов к N), то в каждой корзине у нас будет по одному элементу и мы получим то самое амортизированное O(1). Это — самая примитивная реализация, в реальности, конечно, всё сложнее (плюс существует второй вореант с «открытой адресацией» — это когда в МАССИВЕ хранятся не списки, а сразу пары (ключ, значение), и если при очередной вставке buckets[H] занята, то мы поочерёдно пытаемся вставить в H+1, H+2, H+3 и так далее, причём вместо простого инкремента могут применяться весьма изощрённые техники).
В «Питоне» всё осложняется тем, что нам нужно уметь итерироваться по ключам, и делать это быстро. Как ты понимаешь, перебор всего массива buckets со всеми внутренними списками — это пиздец как долго. Исправить это можно хранением списка всех существующих ключей, и при вставке нового просто добавлять его в конец. Собственно, так мы и можем получить сохранение порядка вставки ключей без порчи асимптот. Такое решение, разумеется, весьма наивно, как там питонухи сделали — хуй знает.
> Кажется, что не всегда)
Честно говоря, «309 ns +- 10 ns» как-то не выглядит надёжно медленнее «320 ns +- 8 ns». А учитывая, что в замере скорости этот питушок брал медиану вместо минимума…
guest # 0 ⇈
Во-вторых если дерево будет не двочиным а Nричным, то при заполненности только первого уровня у меня будет тоже самое, что и у тебя.
Но если мы не хотим коллизий хеша (потому что в обоих наших решениях можно схлопотать O(M), где M кол-во питухов с одинаковым хешем), то придется брать довольно большое N.
В моем решении поиск займет чуть больше времени, но не потребует массива размером N. А в твоем потребует.
gost # 0 ⇈
Если «дерево» будет с достаточно большим N, то это ничем не будет отличаться от стандартной хэш-таблицы, кроме того, что тебе для поиска придётся разыменовывать хуеву тучу лишних уко-ко-козателей, что приведёт пирфоманс прямиком в жопу.
Хэш для таких штук берётся не питушарский, а царский, с максимально равномерным распределением. Поэтому в среднем в каждой корзине будет лежать по M/N (суммарное количество элементов/количество элементов в МАССИВЕ) элементов — эту метрику по-научному называют «load factor».
Если у тебя дерево будет N-ричным, то тебе тоже придётся делать N листьев, лол. По памяти так ты только проиграешь (не говоря уже про пирфоманс).
guest # 0 ⇈
Как и дереву.
>Если «дерево» будет с достаточно большим N, то это ничем не будет отличаться от стандартной хэш-таблицы
Именно
>кроме того, что тебе для поиска придётся разыменовывать хуеву тучу лишних уко-ко-козателей
Если у меня values будут сразу на первом уровне лежать в листьях, то не придется.
Если же дерево будет достаточно глубоким то да, придется.
Зато я буду подгружать с диска только нужные мне куски, а тебе придется выгружать в память весь массив и делать туда случайный доступ. Именно потому я и сказал про "не засрать всю память".
Впрочем, если твой hash целиком влезает в память то да, разумеется он лучше.
gost # 0 ⇈
Остался один шаг: выкинуть ошмётки дерева и получить нормальный, человеческий хэшмассив.
> Зато я буду подгружать с диска только нужные мне куски, а тебе придется выгружать в память весь массив и делать туда случайный доступ.
Стоп-стоп-стоп, это как? У тебя первый уровень N-ричного дерева представляет из себя как раз массив из N элементов, как ты его собрался на куски дробить и почему это нельзя сделать с обычным массивом из N элементов?
> Если же дерево будет достаточно глубоким то да, придется
Джвух уровней будет достаточно, чтобы слить «классической» хэштаблице.
> Впрочем, если твой hash целиком влезает в память то да, разумеется он лучше.
Я очень сильно сомневаюсь, что при разработке словаря в «Питоне» учитывалась необходимость хранения данных, не влезающих в оперативную память.
guest # 0 ⇈
gost # 0 ⇈
guest # 0 ⇈
Дерево можно углубить на след уровень, а массив -- нет.
>У тебя первый уровень N-ричного дерева представляет из себя как раз массив из N элементов,
Ты смешал два моих коммента, или я невнятно выразился.
Если в дереве занят только первый уровень, то я могу хранить там значения, и тогда никаких разыменовываний мне делать будет не нужно.
А потом элементов становится сильно больше.
У дерева отрастает второй уровень. И вот тут уже мне нужно грузить только страницы с нужными мне данными, а тебе же придется иметь огромный массив.
Хотя наверное ты тоже можешь загрузить только кусок, потому что виртуальная память.
Значит ли это, что дерево сосет у hashtable для всех случаев, кроме тех, где данные должны упорядочиваться по значению?
gost # 0 ⇈
А как ты узнаешь, какие тебе нужны страницы? Ты же дерево строишь по хэшу, то есть очередной ключ окажется в абсолютно произвольном куске дерева. Если бы дерево было построено по самим ключам, тогда бы можно было делать предположения — например, что похожие ключи будут лежать где-то рядом.
> Значит ли это, что дерево сосет у hashtable для всех случаев, кроме тех, где данные должны упорядочиваться по значению?
В случаях, когда данных мало, а памяти много (гигабайт данных, десять гигабайт памяти, например) — да. Но когда данных становится очень много, и тратить гигабайты оперативы на пустые корзины становится затратно — тогда уже дерево вырывается вперёд. В этом случае, кстати, основным источников тормозов будут обращения к диску, так что промахи кэша практически перестанут влиять на скорость.
guest # 0 ⇈
Считаю их адреса из узлов дерева.
Пусть первый уровень лежит в странице A.
Второй -- в страницах B и С.
Третий -- D, E, и F.
Я читаю A, затем C и потом E.
>и тратить гигабайты оперативы на пустые корзины становится затратно
Я к этому и клонил, когда говорил про засирание памяти, но потом понял, что реально держать в памяти гигабайты пустого массива не нужно: ОС не будет ничего в память писать, пока ты туда в первый раз не обратишьтся.
gost # 0 ⇈
Ну вот, а в случае с массивом достаточно вычислить хэш и загрузить в память в точности ту корзину, которую надо.
guest # 0 ⇈
Сначала я думал о том, что все корзины придется держать в памяти, потом понял, что менджер виртуальной памяти прекрасно загрузит мне страницу с нужной корзиной.
Главное, чтобы твоя корзина не пересекала границу страницы
guest # 0 ⇈
В питоне, как я понял, они сделали отдельный массив с ключами
gost # 0 ⇈
Как в «Питоне» реализовано — не знаю, не смотрел.
bormand # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
> держать в корзинах кортеж (ключ, значение, указатель_на_ключ_в_списке),
То-есть я за O(1) нашел нужный мне ключ, и дальше по нему нашел его место в массиве, и пошел на массиву читать следующие ключи?
gost # 0 ⇈
А можно, например, хранить список указателей на вставленные кортежи:
В этом случае, кстати, можно будет вспомогательный список преобразовать в дерево (ключ — порядковый номер вставки), тогда удоление элемента будет O(logN).
guest # 0 ⇈
Ведь если бы не оно, то можно было бы использовать этот самый hashtable и течь
gost # 0 ⇈
guest # 0 ⇈
gost # 0 ⇈
А вообще, усложнение внутренней реализации для ускорения/улучшения стандартной библиотеки — это абсолютно нормально. Люди, которые делают делают реализацию языка, нужны именно для того, чтобы писать сложные вещи, которыми смогут пользоваться их менее продвинутые коллеги.
guest # 0 ⇈
Правда это ускорение всё равно пойдет по пизде, если я буду читать И ключ И значение.
Но вероятно обычно значения получают не у всех ключей (иначе логичнее было бы хранить лист туплов)
Кстати, в теории в бакете можно держать кол-во дырок до следующего непустого бакета (будет такой вот "связанный" список), но прыгать по нему будет крайне хуёво: придется или читать из памяти охулион пустых ячеек, или прыгать по страницам как блоха дроча диск.
>тобы писать сложные вещи,
Ради бога, но лишь бы это писалось ради серьезных задач.
"Сохранение порядка вставки у дикта" такой задачей мне не кажется.
А вот скорость итерации -- вполне.
gost # 0 ⇈
Ну, собственно, сначала «CPython» перешёл на новую реализацию, которая сохраняет порядок ключей (то ли в 3.5, то ли в 3.6), и только потом это поведение зафиксировали официально.
Статья про всю эту питушню: https://pbedn.github.io/post/ordered-dict-officially-ordered/.
guest # 0 ⇈
В идеальном мире хэш(словарь, карта, ассоц. массив) в первую очередь используется для получения значения по ключу, а не для итерации, так что было бы здорово оставить его честным hashtable без всяких дополнительных хуйней, заполняющих память (и влияющих на скорость).
Для тех же, кому нужно итерироваться по ключам -- сделать другую структуру (с массивом ключей рядышком).
Правда, это заставило бы программиста думать, и сильно усложнило бы язык.
gost # 0 ⇈
А по поводу отдельных структур на каждый чих хорошо сказано в вышеупомянутой статье:
(Кстати, я тоже без гугла не скажу, чем отличается std::scoped_lock от std::lock_guard и зачем они оба нужны, если есть std::unique_lock).
UPD: И да, «хэш(словарь, карта, ассоц. массив) в первую очередь используется для получения значения по ключу» не выглядит совсем уж очевидным утверждением.
guest # 0 ⇈
The Go language designers noticed that people were relying on the fact that keys were normally stored in the order they were added in, so they randomized the order in which the keys are iterated over. Thus, if you want to output keys in the order they were added in, you need to keep track of which value is in which position in the order yourself
gost # 0 ⇈
UPD: Из пепа:
Какая разница подходов )))
guest # 0 ⇈
почему?
А для чего хеш?
gost # 0 ⇈
Потому что лично я часто вижу в питонокоде конструкцию «for key in some_dict: ...» и не могу бездоказательно согласиться с тем, что операция получения доступа по ключу настолько превалирует над итерацией, что последнюю можно игнорировать.
guest # 0 ⇈
Если бы явно написали: "иди итерируйся в другое место, здесь dict не для этого", то все бы 10 раз подумали прежде чем.
А то небось питухи вместо листа пар используют дикт, и текут.
Кстати, в пандан: в коко есть "mutableSetOf<>() ". Так вот он создает не HashSet, а LinkedHashSet, то-есть тоже insertion order сохраняется.
Коко присоединился к остальным языкам, которые это делают
gost # 0 ⇈
guest # 0 ⇈
То-есть будет два дикта: оптимизированный для итерации и по памяти.
Но я не то чтобы предлагаю, я скорее теоретизирую, потому что понимаю, что в 99% случаев это не важно
gost # 0 ⇈
nemyx # 0 ⇈
gost # 0 ⇈
Нет, поиск конкретного ключа во всех этих вореантах никак не изменяется. Вспомогательный список нужен для того, чтобы быстро итерироваться по всем ключам. А «указатель_на_ключ_в_списке» — чтобы можно было удалять элемент за O(1): ищешь его в таблице за O(1), удаляешь его из вспомогательного списка (тоже за O(1) благодаря тому, что у тебя сразу есть адрес нужного элемента вспомогательного списка), удаляешь из корзины ещё за один O(1).
guest # 0 ⇈
Хочу все ключи от K8 и K99.
Я могу найти K8 за O(1). Затем, я иду в список по смешению "указатель_на_ключ_в_списке", и дальше последовательно читаю ключи.
gost # 0 ⇈
guest # 0 ⇈
Но не в стандартной либле
http://www.grantjenks.com/docs/sortedcontainers/performance-load.html
>Sorted Containers uses a segmented-list data structure similar to a B-tree limited
gost # 0 ⇈
guest # 0 ⇈
есть ощущение, что она не линейна
хотя там и размер не линеен
gost # 0 ⇈
Может, у этих контейнеров поддерживаются какие-то хитрые свойства?
guest # 0 ⇈
строчку
"Если у меня values будут сразу на первом уровне лежать в листьях, то не придется."
следует читать как
"На каждом уровне мне придется делать бинарный поиск, например"
bormand # 0 ⇈
Fike # 0 ⇈
ахаха. такие анскилябры, что хуевый вариант оказался менее хуевым первого.
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
guest # 0 ⇈
gost # 0 ⇈
Какие разработчики игр «Facebook» и «Google» )))
3.14159265 # 0 ⇈
Не совсем.
Там линкед лист бакетов, ключи в одном экземпляре, просто к ним прикручены next/prev.
nemyx # 0 ⇈
Такая же питушня.
jojaxon # 0 ⇈
guest # 0 ⇈
в перле сортирнулось по хешу ключа, и тоже не совпало
3.14159265 # 0 ⇈
Няшно.
3.14159265 # 0 ⇈
> b = {2:3, 1:2}
> print(a == b)
Сранно. Но смотря на этот код я уже ожидаю подвоха. 99% что False.
3.14159265 # 0 ⇈
Кмк, сравнивать сложные типы через == в скриптухе западло.
Должен быть какой-то хитрый map.equals_kv, map.equals_with_order или что-то в этом духе.
gost # 0 ⇈
Змею можно заставить сравнивать словари с учётом порядка ключей через «OrderedDict()», кстати.
3.14159265 # 0 ⇈
Как работает == никто точно не скажет, особенно когда типы разные (пусть даже это разные реализации мап).
А когда ЯВНО указан метод для сравнения всё ясно и понятно.
guest # 0