- 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 30.06.2020 22:22 # 0
а) питух дерьмо
б) for i in xrange и i in a не гарантируют одинаковый порядок ключей
в) на сравнение словарей это влияет, а вот на сравнение строк еще как
г) возвращаемся к тому, что питух дерьмо, ибо мапа не должна зависеть от порядка объявления ключей
д) сам-то принт чего не сделаешь да не посмотришь
gost 30.06.2020 22:26 # +2
bormand 30.06.2020 23:24 # +1
Лучше бы отсортировали по алфавиту. Кому нахуй нужен этот порядок добавления?
Я вот в другом порядке вторую мапу набью. И она будет равна первой т.к. при сравнении порядок не играет роли. А json представление у них будет разное т.к. порядок обхода разный. Т.е. тройка не решает эту проблему.
З.Ы. А решить эту проблему можно только сортировкой перед сериализацией в жсон. Почти как DER в ASN.1
gost 30.06.2020 23:38 # +1
Какую проблему-то? В «Питоне» «JSON» — это просто строка, о её внутренностях «Питон» ничего не знает и знать не должен. Никакой проблемы в этом нет.
Вот если бы он словари сравнивал порядкозависимо, тогда да, был бы багор.
bormand 30.06.2020 23:50 # 0
Т.е. в терминах ASN.1 это аналог BER но не DER.
Desktop 02.07.2020 11:44 # 0
- зачем? зачем?
bormand 02.07.2020 11:47 # 0
Хотя, в json, конечно, из-за пробелов и переносов строк все полимеры будут просраны. Всё-таки в двоичных форматах единства представления легче добиться.
Desktop 02.07.2020 11:56 # 0
Чисто для сравнения двух джейсонов?
gost 02.07.2020 12:00 # 0
Это-то как раз не проблема, достаточно просто не ставить никакие пробелы и переносы строк. А вот что меня беспокоит — так это представление плавающих питухов. Можно ли гарантировать, что один и тот же питух будет сериализован в одну и ту же строку на любом компьютере?
Desktop 02.07.2020 12:01 # 0
bormand 02.07.2020 12:05 # 0
Надо тестить старые сборки питона или сборки под другие платформы. Вот там могут быть отличия.
Desktop 02.07.2020 12:06 # 0
Я думал, надо проверять разные языки и сериализаторы
gost 02.07.2020 12:07 # 0
bormand 02.07.2020 12:09 # 0
gost 02.07.2020 12:06 # 0
На своём проверил, осталось проверить все остальные:
bormand 02.07.2020 12:08 # +1
Для всех остальных чисел. А то вдруг ты просто удачное число выбрал.
gost 02.07.2020 12:11 # 0
Desktop 02.07.2020 12:10 # +1
-
Какой багор)))
gost 02.07.2020 12:12 # 0
Desktop 02.07.2020 12:46 # 0
Если сделать из дабла строку при помощи интерполяции, то там всё будет окей.
bormand 02.07.2020 12:12 # 0
MAKAKA 02.07.2020 12:40 # 0
А как ее всякие говны выводят -- пофиг же
Desktop 02.07.2020 12:44 # 0
MAKAKA 02.07.2020 12:48 # 0
Достаточно сказать "в кроссплатформенном формате JSON индеец имеет такое вот направление"
Desktop 02.07.2020 12:50 # 0
Во-вторых, JSON это человекочитаемый формат.
Потому сериализовывать нужно в простые дроби.
MAKAKA 02.07.2020 12:52 # 0
>человекочитаемый
а, ну тогда вам шашечки, или ехать?
Или у нас человекочитаемый формат, или ieee-754.
Имхо, для передачи данных между программами человекочитаемый формат не нужен.
Desktop 02.07.2020 12:53 # 0
Осилили же как-то printf'ы и прочие логи с выводом плавучки без потери точности.
MAKAKA 02.07.2020 12:55 # 0
Desktop 02.07.2020 12:56 # 0
Десериализация в следующем номере или по короткому номеру
MAKAKA 02.07.2020 13:01 # 0
* Сериализовать питуха так, чтобы его мог понять человек
* Сериализовать питуха так, чтобы его мог понять компутер.
Человек -- существо слабое, и нет большой беды в том, что часть точности питуха проебется.
Тут можно сделать printf из любого практически языка программирования.
Компьютеру же хочется получить питуха точь-в-точь таким, каким его закодировали на той стороне (разумеется, если софт и хард поддерживают питухов такого размера).
Обидно будет узнать, что я передал сообщение по цепочке от компа A к компу B, а оттуда к компу C, и с каждым шагом в нем менялся питух.
Это как с аналоговой пленочной аудиокассетой: чем больше раз переписал песню -- тем она хуёвее.
Так быть не должно.
К сожалению, нужный компьютеру питух человеку не читаем.
Потому можно ввести два вида питуха:
unskillable-petuh: для человека
tsar-petuh aka strict-petuh: для компа. В Hex.
bormand 02.07.2020 12:57 # 0
guest8 02.07.2020 12:58 # −999
bormand 02.07.2020 13:00 # 0
Desktop 02.07.2020 12:59 # 0
guest8 02.07.2020 13:00 # −999
gost 02.07.2020 13:01 # +2
bormand 02.07.2020 13:03 # 0
Типа пишешь 0.1 а получаешь 0.99999999 или 0.100000001. Потому что между ними более подходящих чисел во флоате нет.
Desktop 02.07.2020 13:04 # +1
bormand 02.07.2020 13:05 # 0
gost 02.07.2020 13:05 # 0
bormand 02.07.2020 13:07 # 0
Desktop 02.07.2020 13:12 # 0
Если у нас мантисса на 4 бита, то туда поместится 16 значений, а это всего два порядка в десятичной.
Но у меня с переводами между системами немного всё проржавело, могу и хуйню написать ненароком.
bormand 02.07.2020 13:14 # +1
З.Ы. Хотя, наверное, можно округлить в нужную сторону чтобы потом при обратном преобразовании звёзды сошлись... Но это уже не "без потерь", а просто "обратимо несмотря на погрешность".
MAKAKA 02.07.2020 13:19 # 0
1111 -- 15
Потому, что это будет так же нечитаемо, как 0xF?
bormand 02.07.2020 13:20 # 0
MAKAKA 02.07.2020 13:23 # 0
bormand 02.07.2020 13:27 # 0
Реально без потерь они означают 0.625, 0.750 и 0.875.
Но у нас битов даже на один десятичный разряд не набирается, поэтому мы смело можем их округлить до 0.6, 0.8 и 0.9. Ну и когда мы будем их переводить обратно в двоичное, то получим то что и было на входе.
Т.е. вроде и обратимо, но 0.101 (2) это нихуя не 0.6. Хотя и рядом.
Видимо вот такой приём и подразумевается как "вывод без потерь точности".
bormand 02.07.2020 12:56 # 0
Ну или двоичные дроби. Впрочем ни то ни другое неюзабельно для человека.
Вот будет там какое-нибудь 1609/512 и ты даже не подумаешь, что это кусок пи.
Desktop 02.07.2020 13:00 # 0
И Пи я узнаю из 3.14блабла, да. А вот там какую-нибудь постоянную Планка уже фиг, а потому какая мне разница, какая там дробь?
bormand 02.07.2020 12:53 # 0
MAKAKA 02.07.2020 12:54 # 0
Хочешь кексом, хочешь базой64, хочешь чем хочешь.
Про читаемость https://govnokod.ru/26782#comment556851
bormand 30.06.2020 23:31 # +1
gost 30.06.2020 23:35 # 0
bormand 30.06.2020 23:53 # +2
Именно поэтому я за кресты, где всё просто и понятно: есть отсортированная мапа и есть неотсортированная мапа, в обоих случаях всем похуй на порядок добавления.
З.Ы. В питоне отсортированной мапы, кстати, нету.
MAKAKA 30.06.2020 23:55 # 0
gost 30.06.2020 23:58 # 0
bormand 01.07.2020 00:08 # +1
gost 01.07.2020 09:25 # 0
В «PEP 468» это сделали для того, чтобы сохранить порядок аргументов в **kwargs: https://www.python.org/dev/peps/pep-0468/#id6.
А вообще, «dict» — это хэш-массив, его ключи совершенно не обязаны быть сравнимыми/сортируемыми.
bormand 01.07.2020 11:08 # +1
guest8 01.07.2020 11:17 # −999
bormand 01.07.2020 11:19 # 0
guest8 01.07.2020 11:20 # −999
bormand 01.07.2020 11:23 # 0
В пхп вроде тоже есть.
guest8 01.07.2020 11:26 # −999
bormand 01.07.2020 11:31 # 0
gost 01.07.2020 11:35 # 0
https://govnokod.ru/26415#comment524714
gost 01.07.2020 11:38 # 0
guest8 01.07.2020 11:48 # −999
guest8 01.07.2020 11:59 # −999
Fike 01.07.2020 12:17 # 0
gost 01.07.2020 11:24 # 0
guest8 01.07.2020 11:58 # −999
gost 01.07.2020 12:02 # 0
Так смысл не в том, чтобы их отсортировать, смысл в том, чтобы показать их в том порядке, в каком они были переданы в функцию.
> Но почему тогда явно не заказать ordereddict?
Потому что тогда тебе придётся вместо простого «f(a=1, b=2, c=3)» писать питушарское «f(OrderedDict((a, 1), (b, 2), (c, 3)))» (не знаю, какой там точно у него коньструктор, мог наврать).
Мне, в общем-то, наиболее полезным показался последний пример, с «Specifying argument priority by order».
guest8 01.07.2020 12:11 # −999
gost 01.07.2020 12:43 # 0
«kwargs» — это просто название аргумента, оно может быть любым. То, что в этот аргумент складываются именованные параметры, определяют две звёздочки перед нем. В пепе, в разделе альтернатив, есть предложение расширить синтаксис тремя звёздочками, но это, очевидно, хуёвая идея. «New syntax is only added to Python under the most dire circumstances».
guest8 01.07.2020 13:10 # −999
gost 01.07.2020 13:14 # 0
Для этого разработчикам «Питона» придётся расширить синтаксис, а это — плохая идея. К расширению синтаксиса следует прибегать только в самых печальных обстоятельствах, когда без этого будет совсем уж говно.
guest8 01.07.2020 10:19 # −999
gost 01.07.2020 10:24 # 0
https://www.python.org/dev/peps/pep-0468/#id6
> есть три кейса
Два кейса. Сортировать по ключу нельзя, потому что ключи не обязаны быть сравнимыми. Собственно, они не обязаны даже быть одного типа. А между «сохранять порядок вставки» и «не сохранять порядок вставки» выбор, при прочих равных, очевиден: чем меньше в языке неопределённости, тем лучше.
nemyx 01.07.2020 10:27 # 0
https://www.php.net/manual/ru/function.ksort.php
Есть даже krsort, которая сортирует по убыванию ключей. И даже есть uksort, которой ты можешь подсунуть свой компаратор:
https://www.php.net/manual/ru/function.uksort.php
Именно поэтому я за «PHP».
guest8 01.07.2020 10:33 # −999
gost 01.07.2020 10:44 # 0
А дали такую гарантию после того, как в «CPython» изменили реализацию словаря на такую, которая гарантировала сохранение порядка вставки. И она оказалась быстрее, чем старая.
> Ты может и для сета хочешь сохранять порядок?
А такой сет вполне можно эмулировать имеющимся словарём, причём с сохранением всех асимптот.
guest8 01.07.2020 11:01 # −999
gost 01.07.2020 11:22 # 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». А учитывая, что в замере скорости этот питушок брал медиану вместо минимума…
guest8 01.07.2020 11:45 # −999
gost 01.07.2020 11:56 # 0
Если «дерево» будет с достаточно большим N, то это ничем не будет отличаться от стандартной хэш-таблицы, кроме того, что тебе для поиска придётся разыменовывать хуеву тучу лишних уко-ко-козателей, что приведёт пирфоманс прямиком в жопу.
Хэш для таких штук берётся не питушарский, а царский, с максимально равномерным распределением. Поэтому в среднем в каждой корзине будет лежать по M/N (суммарное количество элементов/количество элементов в МАССИВЕ) элементов — эту метрику по-научному называют «load factor».
Если у тебя дерево будет N-ричным, то тебе тоже придётся делать N листьев, лол. По памяти так ты только проиграешь (не говоря уже про пирфоманс).
guest8 01.07.2020 12:09 # −999
gost 01.07.2020 12:40 # 0
Остался один шаг: выкинуть ошмётки дерева и получить нормальный, человеческий хэшмассив.
> Зато я буду подгружать с диска только нужные мне куски, а тебе придется выгружать в память весь массив и делать туда случайный доступ.
Стоп-стоп-стоп, это как? У тебя первый уровень N-ричного дерева представляет из себя как раз массив из N элементов, как ты его собрался на куски дробить и почему это нельзя сделать с обычным массивом из N элементов?
> Если же дерево будет достаточно глубоким то да, придется
Джвух уровней будет достаточно, чтобы слить «классической» хэштаблице.
> Впрочем, если твой hash целиком влезает в память то да, разумеется он лучше.
Я очень сильно сомневаюсь, что при разработке словаря в «Питоне» учитывалась необходимость хранения данных, не влезающих в оперативную память.
guest8 01.07.2020 12:42 # −999
gost 01.07.2020 12:44 # 0
guest8 01.07.2020 13:08 # −999
gost 01.07.2020 13:23 # 0
А как ты узнаешь, какие тебе нужны страницы? Ты же дерево строишь по хэшу, то есть очередной ключ окажется в абсолютно произвольном куске дерева. Если бы дерево было построено по самим ключам, тогда бы можно было делать предположения — например, что похожие ключи будут лежать где-то рядом.
> Значит ли это, что дерево сосет у hashtable для всех случаев, кроме тех, где данные должны упорядочиваться по значению?
В случаях, когда данных мало, а памяти много (гигабайт данных, десять гигабайт памяти, например) — да. Но когда данных становится очень много, и тратить гигабайты оперативы на пустые корзины становится затратно — тогда уже дерево вырывается вперёд. В этом случае, кстати, основным источников тормозов будут обращения к диску, так что промахи кэша практически перестанут влиять на скорость.
guest8 01.07.2020 13:29 # −999
gost 01.07.2020 13:33 # 0
Ну вот, а в случае с массивом достаточно вычислить хэш и загрузить в память в точности ту корзину, которую надо.
guest8 01.07.2020 13:35 # −999
guest8 01.07.2020 13:15 # −999
gost 01.07.2020 13:27 # 0
Как в «Питоне» реализовано — не знаю, не смотрел.
bormand 01.07.2020 13:29 # 0
guest8 01.07.2020 13:31 # −999
guest8 01.07.2020 13:30 # −999
gost 01.07.2020 13:38 # 0
А можно, например, хранить список указателей на вставленные кортежи:
В этом случае, кстати, можно будет вспомогательный список преобразовать в дерево (ключ — порядковый номер вставки), тогда удоление элемента будет O(logN).
guest8 01.07.2020 13:40 # −999
gost 01.07.2020 13:43 # 0
guest8 01.07.2020 13:45 # −999
gost 01.07.2020 13:51 # 0
А вообще, усложнение внутренней реализации для ускорения/улучшения стандартной библиотеки — это абсолютно нормально. Люди, которые делают делают реализацию языка, нужны именно для того, чтобы писать сложные вещи, которыми смогут пользоваться их менее продвинутые коллеги.
guest8 01.07.2020 13:56 # −999
gost 01.07.2020 14:02 # 0
Ну, собственно, сначала «CPython» перешёл на новую реализацию, которая сохраняет порядок ключей (то ли в 3.5, то ли в 3.6), и только потом это поведение зафиксировали официально.
Статья про всю эту питушню: https://pbedn.github.io/post/ordered-dict-officially-ordered/.
guest8 01.07.2020 20:48 # −999
gost 01.07.2020 21:06 # 0
А по поводу отдельных структур на каждый чих хорошо сказано в вышеупомянутой статье:
(Кстати, я тоже без гугла не скажу, чем отличается std::scoped_lock от std::lock_guard и зачем они оба нужны, если есть std::unique_lock).
UPD: И да, «хэш(словарь, карта, ассоц. массив) в первую очередь используется для получения значения по ключу» не выглядит совсем уж очевидным утверждением.
guest8 01.07.2020 21:07 # −999
gost 01.07.2020 21:08 # 0
UPD: Из пепа:
Какая разница подходов )))
guest8 01.07.2020 21:09 # −999
gost 01.07.2020 21:14 # 0
Потому что лично я часто вижу в питонокоде конструкцию «for key in some_dict: ...» и не могу бездоказательно согласиться с тем, что операция получения доступа по ключу настолько превалирует над итерацией, что последнюю можно игнорировать.
guest8 01.07.2020 21:17 # −999
gost 01.07.2020 21:20 # 0
guest8 01.07.2020 21:25 # −999
gost 01.07.2020 21:25 # 0
nemyx 01.07.2020 21:27 # +1
gost 01.07.2020 13:42 # 0
Нет, поиск конкретного ключа во всех этих вореантах никак не изменяется. Вспомогательный список нужен для того, чтобы быстро итерироваться по всем ключам. А «указатель_на_ключ_в_списке» — чтобы можно было удалять элемент за O(1): ищешь его в таблице за O(1), удаляешь его из вспомогательного списка (тоже за O(1) благодаря тому, что у тебя сразу есть адрес нужного элемента вспомогательного списка), удаляешь из корзины ещё за один O(1).
guest8 01.07.2020 13:47 # −999
gost 01.07.2020 13:52 # 0
guest8 01.07.2020 14:12 # −999
gost 01.07.2020 14:18 # 0
guest8 01.07.2020 14:19 # −999
gost 01.07.2020 14:22 # 0
Может, у этих контейнеров поддерживаются какие-то хитрые свойства?
guest8 01.07.2020 12:20 # −999
bormand 01.07.2020 11:07 # 0
Fike 01.07.2020 12:20 # 0
ахаха. такие анскилябры, что хуевый вариант оказался менее хуевым первого.
gost 01.07.2020 12:41 # 0
bormand 01.07.2020 12:44 # 0
gost 01.07.2020 12:46 # 0
bormand 01.07.2020 12:48 # 0
gost 01.07.2020 12:54 # 0
guest8 01.07.2020 12:58 # −999
gost 01.07.2020 13:02 # +1
Какие разработчики игр «Facebook» и «Google» )))
3.14159265 03.07.2020 18:44 # 0
Не совсем.
Там линкед лист бакетов, ключи в одном экземпляре, просто к ним прикручены next/prev.
nemyx 01.07.2020 07:35 # 0
Такая же питушня.
jojaxon 01.07.2020 07:56 # +1
guest8 01.07.2020 10:32 # −999
3.14159265 03.07.2020 19:00 # 0
Няшно.
3.14159265 03.07.2020 18:43 # 0
> b = {2:3, 1:2}
> print(a == b)
Сранно. Но смотря на этот код я уже ожидаю подвоха. 99% что False.
3.14159265 03.07.2020 18:47 # 0
Кмк, сравнивать сложные типы через == в скриптухе западло.
Должен быть какой-то хитрый map.equals_kv, map.equals_with_order или что-то в этом духе.
gost 03.07.2020 18:51 # 0
Змею можно заставить сравнивать словари с учётом порядка ключей через «OrderedDict()», кстати.
3.14159265 03.07.2020 18:59 # 0
Как работает == никто точно не скажет, особенно когда типы разные (пусть даже это разные реализации мап).
А когда ЯВНО указан метод для сравнения всё ясно и понятно.
guest8 30.06.2020 22:33 # −999