1. PHP / Говнокод #14239

    +166

    1. 1
    if (substr(json_encode($row['list']), 0, 1) == '[') {

    Такой вот аналог is_array()

    Запостил: Lowezar, 17 Декабря 2013

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

    • Не совсем корректное описание добавил. Это такая проверка является ли массив ассоциативным. Надо признать, совсем нормального способа в РНР нет, но обычно array_values($arr) === $arr или ctypedigit(implode('', array_keys($arr))) делают.
      Проверять это через json_encode() всё-таки можно назвать убийством котят...
      Ответить
      • http://ideone.com/kvcOwE
        так не лучше ?
        Ответить
        • Конечно же нет. Оно смотрит только на первый ключ. Вот на такой массив array("0" => 1, "qwe" => 2) оно выдаст 1.
          Ответить
      • Непонятно, зачем такая проверка может понадобиться?
        Ответить
        • Там структура со списком значений может различаться для разных локалей, и в исходной структуре переводчики этого не указывают, поэтому проверяют формат списка [123,456] или {"en_US":[123,456],"fi_FI":[789,987]}.
          Странноватая схема, честно говоря, почему не могли договориться чтоб всегда было вложение с {"*":[123,456]} если не различаются... Но это не ко мне вопрос. :)
          Ответить
          • Понятно, что лишний раз доказывает, что такая проверка не особо нужна в нормальных ситуациях :)

            А эта схема еще странна тем, что непонятно, что делать если нужная локаль не нашлась. Юзать en_US? Юзать первую попавшуюся в массиве?

            P.S. Я всё-таки за схему 1 файл - 1 язык. Она и работает пошустрее, т.к. не надо парсить кучу ненужных в данный момент языков (для пыхи, имхо, актуально). И новые переводы добавлять легко. Единственный минус - нужна тулза для редактирования, которая показывает, какие строки еще забыли перевести. Но без такой тулзы работа переводчика один хрен мазохизм ;)
            Ответить
            • Ну, собственно, переводчики так и пользуются какой-то своей софтварью. Мы имеем от них единый файл со всем-всем-всем. И вот этот самый скрипт, из которого я вытянул говнецо, переводит этот единый файл в более перевариваемый веб-мордой вид. ...переводит переводы. :)
              Ответить
              • > Мы имеем от них единый файл со всем-всем-всем.
                Вот интересно, у этой софтины какая-то централизованная база, с которой работают переводчики, а файл - просто выгрузка из нее. Или же у них там веселый групповой секс с одним файлом? :) Во втором случае я им не завидую...
                Ответить
      • > Надо признать, совсем нормального способа в РНР нет
        Эээ, а вот это тогда что? http://php.net/manual/ru/function.is-array.php

        P.S. А тьфу, дошло, тут нужно именно отличить массив с циферками от ассоциативного массива... Но нахрена?!
        Ответить
        • array('qwe'=>'asd', 'zxc'=>123) - тоже is_array, но ассоциативный, и потому в json ложится не в [] а {}
          Ответить
          • А зачем, на практике, может понадобиться их отличать? Ну кроме сериализации :)
            Ответить
            • См. выше. Но вообще да, за 15 лет мне такую проверку приходилось делать только 1 раз. Сегодня второй, но не сделал, а просто увидел, проходя мимо. :)
              Ответить
      • >Это такая проверка является ли массив ассоциативным. Надо признать, совсем нормального способа в РНР нет
        Ох ё.
        Ответить
        • Дык там, по сути, только ассоциативные массивы и есть. Так что задача в том, как отличить ассоциативный массив, в котором только числовые ключи, от ассоциативного массива, в котором не только числовые ключи ;)
          Ответить
          • А получить ключи и узнать тип нельзя?
            Ответить
          • …count(array_filter(array_keys($arr), 'is_string'))…
            Ответить
            • Таки да. А что делает из_стринг?
              Ответить
            • Да, но это довольно тяжёлый на процессорное время вариант. Я выше написал более производительные варианты (расход памяти обычно не настолько критичен). Хотя, конечно, они с определёнными ограничениями...

              Но более точная проверка с is_string нужна ИМХО ещё реже, чем проверка на ассоциативность в принципе. :)
              Если быть точнее, то из 2 раз на моём опыте ещё не было такого, чтоб array_values($arr) === $arr не подошёл.
              Ответить
              • Т.е. пробежаться по всем ключам и проверить их на is_string в пыхе дороже, чем скопировать весь массив и потом пробежаться по нему и сравнить каждый элемент? :)
                Ответить
                • Я, конечно, давно этот эксперимент ставил, ещё во времена 5.1... Но получалось так, что из-за вызова пользовательской функции сложность была выше. Быстрее всего отрабатывала версия ctypedigit(), разница с array_values была по-моему около 10%. А is_string подвешивался на 10кратное время. :) Сейчас может уже и не так.
                  Ответить
                • дешевле по памяти - дороже по проц. времени) на то она и память же)
                  Ответить
                  • Дык тут такая задача, что на компилируемом языке размен памяти на проц нахер бы не сдался. Просто в пыхе настолько медленный вызов функций, что воспользоваться готовой, копирующей весь массив, а потом еще и сравнивающей казывается быстрее...
                    Ответить
                    • а потом эти люди приходят в серьезное программирование и начинается
                      Ответить
            • Самое интересное, что нам не нужно считать ВСЕ элементы, а достаточно найти первый (если такой имеется), индекс которого is_string...
              Ответить
              • array_filter можно распараллелить.
                Ответить
                • Поиск любого элемента, удовлетворяющего is_string, тоже можно распараллелить :)
                  Ответить
                  • Но скорости это не прибавит.
                    Ответить
                    • Ну как это не прибавит? Еще как прибавит. Даже если не прерывать остальные потоки, если один из них что-то нашел.

                      У поиска только скан (причем при поиске первого - не до конца) и банальный and на слиянии. У фильтра - скан + копирование найденных (т.е. еще и выделение памяти) + слияние результатов в конце. В итоге у поиска меньше бесполезной для данного случая работы.
                      Ответить
                      • Нет, не прибавит. Это почему поиску не нужно копировать? А что возвращать тогда?
                        Ответить
                        • Ок, я действительно криво выразился. Назвал проверку условия поиском. Поиск всех элементов это и есть фильтр :)

                          При проверке условия, аля "один из элементов is_string" или "все элементы is_string", тредам достаточно вернуть bool, а результаты объединить and'ом (или or'ом).

                          При поиске первого или любого элемента надо вернуть только один элемент из каждого треда.

                          Ну неужели эти два варианта не будут быстрее, чем полноценный фильтр, у которого каждый тред должен вернуть массив\список, а потом их еще и нужно объединить? :)
                          Ответить
                          • Поиск и фильтр просто превратятся в одну и ту же операцию, с той разницей, что мы не используем все результаты фильтра, но сгенерировать нам их все равно прийдется.

                            Как бы предположение такое, что мы создаем столько же тредов / процессов, сколько элементов есть в массиве :) Предположительно треды у нас очень дешевые, так что стоимостью создания можно пренебречь.
                            Ответить
                            • Все же проверка предиката будет быстрее, чем фильтр ;) Ей то точно не надо генерировать результаты фильтра.

                              > Как бы предположение такое, что мы создаем столько же тредов / процессов, сколько элементов есть в массиве :) Предположительно треды у нас очень дешевые, так что стоимостью создания можно пренебречь.

                              Представим коня в виде материальной точки, котрая равномерно и прямолинейно движется в вакууме.

                              Ну т.е. это что-то близкое к тем же spark'ам в хаскеле, нежели к традиционному разбиению на крупные подзадачи и исполнению их в worker thread?
                              Ответить
                              • Не, не все не так плохо. Наш моск так именно и работает. Ну или по крайней мере моск Джеффа Хокинса.
                                Ответить
      • > Это такая проверка является ли массив ассоциативным.

        return true;
        Ответить

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