1. C# / Говнокод #18452

    +145

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    var lst = new List<string>();
    foreach (String parameterName in parameters.Keys) // parameters это Dictionary<String, Object>
    {
    	lst.Add(parameterName + ": " + parameters[parameterName].ToString());
    }

    Долгий вариант перебора словаря: перебор ключей в цикле и на каждой итерации получение по ключу значения из словаря

    Запостил: vldalx, 08 Июля 2015

    Комментарии (136) RSS

    • И чо?
      Ответить
    • Ну а че особенного, просто автор этого кода раньше на js писал ;)
      Ответить
      • А как надо?
        Ответить
        • parameters.Select(i=>string.Format("{0}: {1}", i.Key, i.Value)).ToList()
          Ответить
          • да, тоже, как сторонник linq, предпочитаю так писать
            а если и дальше говорить о производительности, то простое сцепление строк, через + или string.concat работает быстрее чем string.Format
            единственный плюс string.Format это читаемость
            Ответить
            • Вот оно че

              Значит поиск по ключу в хешталице - это медленно, а переливать из одной коллекции в другую - это норма?
              Ответить
      • Вы что-нибудь слышали про сложность алгоритма? Автор этого кода видимо тоже с трудом представляет что это такое.

        Вот такой вариант намного эффективнее:

        var lst = new List<string>();
        foreach (var parameter in parameters)
        {
        lst.Add(parameter.Key + ": " + parameter.Value.ToString());
        }

        более того, в первоначальном варианте, скорость доступа по ключу к элементу словаря колеблется от того, какие строки (т.е. что они из себя представляют) используются в качестве ключа.
        Ответить
        • >> Вы что-нибудь слышали про сложность алгоритма?
          >> Автор этого кода видимо тоже с трудом представляет что это такое.

          Куда уж нам, о Великий!
          Ответить
          • Однако, никто не привел аргументированного доказательства того, что я не прав в данном случае.
            Ответить
            • Гуру, расскажите нам о таинственной и непонятной сложности

              Правда, что она бывает ло-ка-ри-фми-чис-кая?
              Ответить
              • Я рад, что Вы знаете теорию, еще было бы не плохо применять её на практике.
                Жаль, что вы не видите, или не хотите видеть, разницу между двумя кусками кода.
                Ответить
                • Ты приходишь на сайт и сразу встаешь в позу - я умный- все дебилы

                  Не надо так.

                  Тут большинство прекрасно понимает что такое сложность и в чем разница между двумя вариантами
                  Ответить
                  • Не надо обобщать, про ВСЕ дебилы намека не было.
                    Извиняюсь перед bormand.
                    Судя по минусам к коду, когда еще не было никаких комментариев, то не все всё понимают.
                    Ответить
                    • да тут люди с попоболью минусуют скриптами

                      Добро пожаловать в реальный мир на говнокод
                      Ответить
        • А что не так?
          Ответить
        • > Вы что-нибудь слышали про сложность алгоритма?

          А вы?

          Я лично вижу, что оба вариант работают за O(n), где n - размер словаря. Правда, в топике - амортизированное O(n), а в вашем варианте - гарантированное.
          Ответить
          • В идеальном случае, сложность получения элемента словаря по его ключу О(1). В худшем случае O(n).
            Все зависит от количества коллизий при инициализации словаря.
            Ответить
            • > амортизированное
              Ответить
              • ОК, ответ в самом вопросе
                Ответить
                • Кстати, если лукап ключа в хэш-словаре линейный, то и составление этого словаря требовало линейного времени на добавление каждого элемента, что даёт в сумме O(n^2) на конструирование словаря. Следовательно, суммарная сложность работы со словарём не изменилась.
                  Ответить
            • И это так важно? Как получить o(n)?
              Ответить
              • > Как получить o(n)?
                Строить map как вырожденное в список дерево.
                Ответить
                • И как это получить?
                  Ответить
                  • Использовать свой кривой алгоритм.
                    Или попробовать как-то обмануть HashMap.
                    Ответить
                  • Написав корявые хэш-функции? Посмотрев на реализацию хэша в стд-либе и подобрав коллизии?
                    Ответить
                    • >Написав корявые хэш-функции?
                      Они стандартные?

                      >Посмотрев на реализацию хэша в стд-либе и подобрав коллизии?
                      На чужой машине это с некоторого времени не работает, на своей - но зачем?
                      Ответить
                      • > Они стандартные?

                        Ключём в словаре может быть любой тип. Эффективноть работы словаря зависит от качества хэш-функции для типа-ключа, который может быть определён пользователем.

                        В первых версиях jdk была кривая хэш-функция для строк, просматривавшая не всю строку. Из-за этого для некоторых входов (например, доменных имён), было дикое кол-во коллизий.
                        Ответить
                        • >Ключём в словаре может быть любой тип. Эффективноть работы словаря зависит от качества хэш-функции для типа-ключа, который может быть определён пользователем.

                          >foreach (String parameterName in parameters.Keys)
                          www, перелогинься.

                          Для строк хешкод стандартный.
                          Ответить
          • А вот как работает получение пары (ключ, значение) в хешмепе?
            Ответить
            • Да тупо оббегаются все слоты и проверяются на пустоту. Отсюда и почти рандомный порядок.
              Ответить
              • Что значит "оббегаются все слоты", занятые слоты где-то сохранены? А как работает итерация по ключам/значениям?
                Ответить
                • Ну я про итерацию и имел в виду - тупо бежим по всей хеш табличке и обрабатываем все непустые слоты.

                  > где-то сохранены
                  Флаг в каком-то виде всяко есть (возможно неявный, в виде какого-нибудь null'а). Иначе поиск и вставку не реализовать.
                  Ответить
                • http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.HashIterator

                  Вот так в жабе реализован обход мапы.
                  Ответить
                  • > в жабе
                    >openjdk
                    Ты опять?

                    Там Entry[], а Entry в добавок хранит ссылку на next. Т.е. в хешмепе параллельно хранится список ключей/значений? Оригинально.
                    Ответить
                    • Что опять? Думаешь, что в оракловой реализации там что-то другое?

                      P.S. По существу вопросы будут?
                      Ответить
                      • >Что опять?
                        Опять выходишь на связь? Опять называешь openjdk жавой?
                        Ответить
                        • В стандартной либе жабы. Так устроит?
                          Ответить
                          • openjdk - стандартная либа жавы? Нахуй он кстати нужен, чем оракл не устраивает?
                            Ответить
                            • А почему в заголовке файла написано sun?
                              Ответить
                              • Лол, да потому что openjdk сам sun и выложил (а сейчас, емнип, oracle участвует в пилении). Там вроде как только некоторых энтерпрайзных кусков нету, которые им не хотелось открывать.
                                Ответить
                                • Что есть "энтерпрайзные куски" из стандартной библиотеки?
                                  Ответить
                    • > хранится список ключей/значений
                      Так они решают проблему с коллизиями хеша - Entry с одинаковым хешем будут лежать в виде связного списка.
                      Ответить
                      • Ах вот оно зачем. А что такое transient Entry[] table?
                        Ответить
                        • transient - поле не участвует в сериализации. Ну а дальше тупо массив из Entry.
                          Ответить
                          • Кэп, я спросил не что означает эта строчка на яве, а что в этой table хранится.
                            Ответить
                            • Связные списки записей с совпадающим по модулю размера таблицы значением хеша ключа, в которых лежат ключ, значение и хеш ключа.

                              Ваш кэп.

                              P.S. Ну по коду же всё видно...
                              Ответить
                              • > P.S. Ну по коду же всё видно...

                                IDE НЕ ПОДСВЕЧИВАЕТ (tm)
                                Ответить
                                • Да, не подсвечивает. Спасибо что посказал.
                                  Ответить
                              • Ага, то есть для поиска записей нужно пробежаться по всему массиву? Но тогда не будет O(количество записей)
                                Ответить
                                • > нужно пробежаться по всему массиву?

                                  Иди уже поучи матчасть, не позорься.
                                  Ответить
                                  • Сам туда иди. поиска записей -> итерации по записям.
                                    Ответить
                                • Для поиска считаем хеш, берём по модулю количества записей в массиве, и в списке, на который указывает table[i] линейным поиском ищем нужный ключ.

                                  Почитай реализацию get() что ли...
                                  Ответить
                                  • поиска записей -> итерации по записям.
                                    Ответить
                                    • Так ты про итерацию или про поиск?

                                      Для поиска см. выше.

                                      Для итерации - да, пробегаем все слоты. Твоя проблема возникнет только в одном случае - если навставлять миллион элементов и погрохать почти все, причем табличка должна не уметь сжиматься (жабья, как я понимаю, как раз не умеет).

                                      Приведи пример практического сценария, когда это произойдёт.
                                      Ответить
                                      • Каshitцин упоминал про **гарантированный** O(количество записей), которого в таком сценарии, очевидно, не будет.
                                        Ответить
                      • Обожаю "программистов с западным образованием", не знающих, как работает хэш-таблица.
                        Ответить
                        • Программист с парашкинским образованием, объясни, как в классической хеш таблице сделать итерацию по ключам-значениям.
                          Ответить
                          • > как в классической хеш таблице сделать итерацию по ключам-значениям

                            Для этого даже образования не надо, лишь чуточку ума.

                            Пробегаешь по всему массиву бакетов, в каждом бакете посещаешь список пар ключ-значение. Итератору достаточно хранить указатель на текущий бакет и текущую позицию в массиве бакетов.

                            Конкурентные модификации хэш-таблицы в жаве запрещаются.
                            Ответить
                            • >Пробегаешь по всему массиву бакетов
                              Который с дырками?
                              Ответить
                              • > Который с дырками?
                                Да, и что, в чём проблема?
                                Просто скипаешь все дырки, там нулевые укатели. На каждом next() надо бежать до следующего непустого.
                                Ответить
                                • >Да, и что, в чём проблема?
                                  В том, что у тебя на мегабайт может быть одно место? И тогда хуй тебе, а не O(количество элементов)
                                  Ответить
                                  • > у тебя на мегабайт может быть одно место?

                                    И что? Хорошая табличка должна расти с увеличением числа записей, чтобы кол-во бакетов было всегда порядка O(n) от n записей. Поэтому в худшем случае вся итерация в сумме будет работать O(n).

                                    Если планируется удалять много записей, нужна табичка, которая шринкается при низком load factor.
                                    Ответить
                                    • >чтобы кол-во бакетов было всегда порядка O(n) от n записей.
                                      Ты понял, что за хуйню ты сморозил? В O сокращается множитель. Нет, ну O(количество записей) то останется, но множитель может быть неприятным.

                                      А вдруг таблицы которые в языках - плохие?
                                      Ответить
                                      • > В O сокращается множитель.
                                        > множитель может быть неприятным

                                        Ну ты и лалка. Почитай про load factor чтоли.
                                        Специально открыл первую статью на вики - даже там про это написано.
                                        Раз думать тебя так и не научили.
                                        Ответить
                                        • Жабья, кстати, плохая. Она только растёт.
                                          Ответить
                                          • Тогда совсем охуенно. Каshitцин, ты это видел?
                                            Ответить
                                          • > Жабья только растёт.

                                            В крестах (gcc) unordered_map тоже не шринкается. Шарповый Generic.Dictionary тоже.

                                            Что даёт на O(N) на итерацию, где N - максимальный размеров словаря, наблюдаемый за время его существования. Если предположить, что элементы удаляются не сильно чаще, чем добавляются, то получаем эффективное O(n) с константой порядка 2-4.

                                            Видимо, шринк - настолько редкое требование, что его никто не делает из коробки.

                                            Пистоний словарь вроде как может ресайзиться в меньшую сторону, но в коде удаления элементов я этого не нашёл.

                                            Те, у кого сильно специфический ворклоад, вполне могут позволить себе запилить эвристический шринк, чтобы отвязаться от N.
                                            Ответить
                                            • Не только уменьшение, но и итерация по записям, т.к. на скорость поиска количество пустых мест не влияет.
                                              Ответить
                                            • Да в крестах даже вектор не шринкается :)
                                              Ответить
                                              • Кстати, ещё один воркараунд - если capacity стала слишком большой, а итерироваться надо часто - пересоздать таблицу вручную.
                                                Ответить
                                            • Ну вообще логично. Что бы шринк был выгоден нужно, что бы из объемной коллекции удалили больше половины элементов, что довольно редко происходит.

                                              Да и кому надо сам напишет
                                              Ответить
                                              • А в чем проблема добавить лишнюю проверку в удаление?
                                                Ответить
                                                • А в чем проблема вбить тебе дилдо в жопу?

                                                  Проблемы нет, просто не нужно
                                                  Ответить
                                                  • Проблема в том, что через интернет ее не вобьешь, а в реале ты так тем более зассыш. Можешь пока на своей мамке потренироваться.
                                                    Ответить
                                                    • давай адрес. Не я, так Василий приедет
                                                      Ответить
                                                      • Ха-ха, ты на билет в Гермашку уже насосал? обратно не надо, тут тебя похороним за гос. счет.
                                                        Ответить
                                                        • а если обосрался, то и не открывай свой поганый рот ^_^
                                                          Ответить
                                                          • Я обосрался? Ты приедь, а там разберемся, а то ты какашку по почте пришлешь или под дверь нассышь.
                                                            Ответить
                                                            • куда?
                                                              Ответить
                                                              • Гермашка, Бавария.
                                                                Ответить
                                                                • помойка номер 3?

                                                                  координаты GPS дай
                                                                  Ответить
                                                                  • И что они тебе дадут? Ты туда на парашюте из космоса высадишься?
                                                                    Ответить
                                                                    • ссыкло
                                                                      Ответить
                                                                      • >И что они тебе дадут?
                                                                        Ответить
                                                                      • Ведёте себя как малолетние школьники. Ладно сёма, он безнадёжен, но тебе-то уже поумнеть пора.
                                                                        Ответить
                                                                        • Ты так говоришь, как будто я - школьник.
                                                                          Ответить
                                                                        • Да скучно что то, вот и пытаюсь взбугуртить семена.

                                                                          Ум - он скорбь приумножает. Наверное иногда хочется отупеть как сема, вот и несу херню
                                                                          Ответить
                                                                          • >Наверное иногда хочется поумнеть как сема, но все время несу херню
                                                                            Ответить
                                                        • > тебя похороним
                                                          >похороним
                                                          т.е. Ты настолько пидар, что если kegdan приедет тебя пиздить ты обосрешься выйти один.
                                                          Ответить
                                                          • Нет, ну хоронить-то много людей будут. Тут под деревом просто так биомусор зарывать нельзя.
                                                            Ответить
                                        • Тогда у тебя не будет** гарантированного** O(n), лалка.
                                          Ответить
                                          • > Тогда у тебя не будет

                                            У меня будет, лалка. Мне не составляет никакого труда реализовать хэш-таблицу, которая будет гарантировать O(n) итерацию.

                                            То, что дефолтная жаба делает что-то определённым образом не означает, что что-то невозможно.

                                            Кроме того, жабий HashMap поддерживает keySet() которая позволяет быстро обходить только ключи и лукапить значения по ключу, если уж есть сценарий с массовым удалением.
                                            Ответить
                                            • Ну так реализуй и закоммить в жаву, пока на твои царские потуги всем похуй.

                                              >позволяет быстро обходить только ключи
                                              И как она это делает? Отдельно хранит ключи?
                                              Ответить
                            • >> Пробегаешь по всему массиву бакетов

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

                              Может я в терминологии путаюсь, но вроде как словарь в шарпе - это и есть хэш-таблица
                              Ответить
                              • Так выше про жаву сказали, что это односвязный список на случай коллизий.
                                Ответить
        • > Вы что-нибудь слышали про сложность алгоритма?
          Нет, а что это?

          > Автор этого кода...
          ...раньше однозначно писал на js (или perl'е?). Ну просто я не помню других языков, где кроме идиомы из топика ничего не работает.

          > намного эффективнее
          Ну не так уж намного. В общем-то в типичной прикладнухе разницу и не заметить.
          Ответить
          • Профилировщик показал, что таки метод с поиском значения из словаря на 80% медленнее.

            Мой суррогатный тестовый код

            https://ideone.com/kXelZy

            скрины профилировщика ннадо?
            Ответить
            • Но причем тут алгоритмическая сложность?

              Ух ты, сисярп умеет в foreach по словарю?

              > for (int i = 0; i < 10000; i++,key += "1")
              Ключи в 10k символов - такой типичный случай? Сделай что-нибудь поумнее.
              Ответить
              • >> Но причем тут алгоритмическая сложность?
                bormand в http://www.govnokod.ru/18452#comment292495 написал:
                >> В общем-то в типичной прикладнухе разницу и не заметить.

                3_14dar в http://www.govnokod.ru/18452#comment292502 написал:
                >> Ключи в 10k символов - такой типичный случай?
                kegdan в http://www.govnokod.ru/18452#comment292500 написал:
                >> Мой суррогатный тестовый код
                Ответить
                • Что значит суррогатный?
                  Ответить
                  • 3_14dar в http://govnokod.ru/18452#comment292502 написал:
                    >> Ух ты, сисярп умеет в foreach по словарю?
                    >> Что значит суррогатный?
                    3_14dar в http://govnokod.ru/18452#comment292502 написал:
                    >> Сделай что-нибудь поумнее.

                    лол
                    Ответить
                    • Вот и ответь что ты под этим имеешь в виду, лол.
                      Ответить
                      • На google.com ввели фейсконтроль?
                        Ответить
                        • >СУРРОГАТНЫЙ, суррогатная, суррогатное (книжн.). Не настоящий, поддельный, являющийся суррогатом.
                          Поддельный тестовый код?
                          Ответить
                        • дебилов забанили же. Не верешь? На любой форум зайди там 95% вопросов от забаненых.
                          Ответить
                          • И поэтому ты здесь?
                            Ответить
                            • Чувак, скажи, ты где на программиста обучался?
                              Ответить
                            • И поэтому ты дебил. И идешь на хуй.
                              Ответить
                              • Сама нахуй иди, телогрейка.
                                Ответить
                                • Сёма нахуй иди, 3_14dar .
                                  Ответить
                                  • А почему не на питон?
                                    Ответить
                                  • Гость, иди нахуй, гость!
                                    Ответить
                                    • Пососи мой питон 4.0 (в диаметре).
                                      Ответить
                                      • Миллиметра? А почему ты пишешь числа с точкой как пендос какой-то?
                                        Ответить
                                        • * g o a t s e x * g o a t s e x * g o a t s e x *
                                          g                                               g
                                          o /     \             \            /    \       o
                                          a|       |             \          |      |      a
                                          t|       `.             |         |       :     t
                                          s`        |             |        \|       |     s
                                          e \       | /       /  \\\   --__ \\       :    e
                                          x  \      \/   _--~~          ~--__| \     |    x
                                          *   \      \_-~                    ~-_\    |    *
                                          g    \_     \        _.--------.______\|   |    g
                                          o      \     \______// _ ___ _ (_(__>  \   |    o
                                          a       \   .  C ___)  ______ (_(____>  |  /    a
                                          t       /\ |   C ____)/      \ (_____>  |_/     t
                                          s      / /\|   C_____)       |  (___>   /  \    s
                                          e     |   (   _C_____)\______/  // _/ /     \   e
                                          x     |    \  |__   \\_________// (__/       |  x
                                          *    | \    \____)   `----   --'             |  *
                                          g    |  \_          ___\       /_          _/ | g
                                          o   |              /    |     |  \            | o
                                          a   |             |    /       \  \           | a
                                          t   |          / /    |         |  \           |t
                                          s   |         / /      \__/\___/    |          |s
                                          e  |         / /        |    |       |         |e
                                          x  |          |         |    |       |         |x
                                          * g o a t s e x * g o a t s e x * g o a t s e x *
                                          Ответить
              • Кстати, теперь понятно почему код школоло медленнее - 1) считается хэш, в среднем O(n^2) 2) O(n^2) в заголовке цикла из-за +=. Так что разница в сложности есть, но только в коде школы.
                Ответить
            • > на 80% медленнее
              Напугал ежа голой жопой. Т.е. разница только в константе и всего в 2 раза? Причём при диких ключах в ~5000 символов?

              Вот когда этот код будет бутылочным горлышком - можно задуматься о профайлере. А до этого в общем-то похуй.

              P.S. Но мне вариант с парами больше нравится из-за наглядности.

              P.P.S. Попробуй сделать тест на рост сложности - 1к, 10к, 100к.
              Ответить
              • Я и не говорил что разница существенна. Но байтоебам для истерики хватит

                http://download.hdd.tomsk.ru/preview/waefahjh.jpg

                все в миллисекундах

                Словарь заполняется вот так

                for (int i = 0; i < count; i++)
                                dictionary[i.ToString()] = new MyClass();
                Ответить

    Добавить комментарий