Intereting Posts
HTTP-запросы с файловым_компонентом, получение кода ответа dropzone.js загрузка изображений принятаMimeTypes PHP – Преобразование целочисленного целочисленного значения в float с тремя десятичными знаками Файлы PHP не выполняются в Windows-машине Как Центрировать текст в FPDF? Xampp 7.0.1 Apache падает, когда я использую session_start () Использование одного сайта для нескольких доменов в PHP Предупреждение: exec () отключен по соображениям безопасности Исходный код php для генератора файлов PO PHP – подсчитать повторяющиеся значения в двухмерном массиве, а затем отобразить только уникальные значения со счетчиком Разделить данные на 3 столбца Как проверить определенную часть URL-адреса, используя php Как настроить трансформатор данных в Symfony для повторного использования существующих объектов? максимальная длина сообщения и имя переменной Лучший способ разобрать Javascript-файл в PHP, чтобы извлечь массив, определенный внутри него

Лучшая практика: как структурировать массивы – стандарты и соглашения об именах

Какова наилучшая практика в многомерной структуре массива с точки зрения того, какие элементы содержат итератор и элементы детали?

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

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

Например, если у меня есть одномерный массив следующим образом:

$myArray['year']=2012; $myArray['month']='July'; $myArray['measure']=3; // and so on. 

Однако, если бы я хотел, чтобы тот же массив сохранил несколько владельцев истории, я бы добавил еще одно измерение и отформатировал его следующим образом:

 $myArray[$owner]['year']=2012; $myArray[$owner]['month']='July'; $myArray[$owner]['measure']=3; 

Изменить: Чтобы убедиться, что мой пример не отложен или не ведет в правильном направлении, я в основном следую этой структуре:

 $myArray[rowOfData][columnOfData] 

Теперь мой вопрос о принятой конвенции. Должен ли я вместо этого делать следующее?

 $myArray['year'][$owner]=2012; $myArray['month'][$owner]='July'; $myArray['measure'][$owner]=3; 

Изменить: используя это редактирование сверху, должно ли оно быть:

 $myArray[columnOfData][rowOfData] 

Я искал соглашения об именах массивов, но продолжаю сталкиваться с статьями, которые спорят о том, следует ли указывать массивы как множественные числа или нет. То, как я назвал их, кажется более логичным, и я думаю, что это следует за структурой, которая больше напоминает объект, т. object->secondaryLevel->detail но для всех, кого я знаю, я все время занимаюсь этим. Поскольку я все больше и больше занимаюсь программированием, я бы предпочел изменить свои привычки, если они ошибаются.

Есть ли принятый стандарт или все идет с массивами? Если бы вы искали код, написанный кем-то другим, какой формат ожидал бы? Я понимаю, что любая структура, которая имеет смысл / интуитивно понятна, принимается.

Также с точки зрения итерации, какая из следующих функций более интуитивная?

 for($i=0;$i<$someNumber;$i++) { echo $myArray[$i]['year']; // OR echo $myArray['year'][$owner]; } 

Редактировать: у меня был этот пост с тегами как c # и Java, потому что я хотел получить некоторые мнения вне PHP-программистов. Я думаю, что, поскольку массивы используются на многих разных языках, было бы неплохо получить некоторый вклад от программистов в разных языках.

Ваш вопрос субъективен, поскольку каждый может иметь другой подход к ситуации, о которой вы заявили, и вы разумно даже задать вопрос; Как лучше назвать ваши переменные, классы и т. Д. Грустно сказать, что я трачу больше времени, чем я хочу признать определение лучших имен переменных, которые имеют смысл и удовлетворяют требованиям. Моя конечная цель – написать код, который « сам документирует ». При написании самодокументирующего кода вы обнаружите, что гораздо проще добавлять функции или исправлять недостатки по мере их возникновения.

На протяжении многих лет я пришел к выводу, что эти практики лучше всего подходят для меня:

Массивы: всегда множественное число

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

 // With a plural array it's easy to access a single element foreach ($students as $student) {} // Makes more sense semantically do {} (while (count($students) > 0); 

Массивы объектов> глубокие многомерные массивы

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

 class Owner { public $year; public $measure; public $month; } // Demonstrative hydration for ($i = 1 ; $i <= 3 ; $i++) { $owner = new Owner(); $owner->year = 2012; $owner->measure = $i; $owner->month = rand(1,12); $owners[] = $owner; } 

Теперь вам нужно только перебирать плоский массив, чтобы получить доступ к необходимым вам данным:

 foreach ($owners as $owner) { var_dump(sprintf('%d.%d: %d', $owner->month, $owner->year, $owner->measure)); } 

Самое интересное в этом подходе к массиву объектов – насколько легко будет добавлять улучшения, что, если вы хотите добавить имя владельца? Нет проблем, просто добавьте переменную-член в свой класс и немного измените гидратацию:

 class Owner { public $year; public $measure; public $month; public $name; } $names = array('Lars', 'James', 'Kirk', 'Robert'); // Demonstrative hydration for ($i = 1 ; $i <= 3 ; $i++) { $owner = new Owner(); $owner->year = 2012; $owner->measure = $i; $owner->month = rand(1,12); $owner->name = array_rand($names); $owners[] = $owner; } foreach ($owners as $owner) { var_dump(sprintf('%s: %d.%d: %d', $owner->name, $owner->month, $owner->year, $owner->measure)); } 

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

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

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

Основываясь на вашем примере выше, хотя способ, которым я бы справился с вышеуказанным, вероятно:

 $array[$year][$month] = $measure; 

Вам не нужен конкретный элемент «measure». Или если у вас есть два элемента в месяц:

 $array[$year][$month] = array('measure' => $measure, 'value'=>$value); or $array[$year][$month]['measure'] = $measure; $array[$year][$month]['value'] = $value; 

Тогда вы можете пойти:

 for($year = $minYear; $year <= $maxYear; $year++) { // Or "foreach" if consecutive for ($month = 1; $month <= 12; $month++) { if (isset($array[$year][$month])) { echo $array[$year][$month]['measure']; // You can also check these exist using isset if required echo $array[$year][$month]['value']; } else { echo 'No value specified' } } } 

Надеюсь, что это поможет с вашим мышлением.

Ты делаешь это правильно. Вы должны понимать, что PHP не имеет реальных многомерных массивов; то, что вы ищете, представляет собой массив массивов, каждый из которых является одномерным. Основной массив хранит указатели («итератор», как вы выразились). Из-за этого, первый ряд – единственный разумный способ:

В вашем конкретном примере вы можете представить свой двумерный массив как содержащий набор объектов, каждый из которых имеет значения для 'year', 'month', и 'measure' (плюс первичный ключ, 'owner' ). Заполнив основной индекс, вы можете обратиться к каждой строке двумерного массива следующим образом: $myArray[$owner] . Каждое такое значение представляет собой трехэлементный массив с ключами 'year', 'month', и 'measure' . Другими словами, он идентичен вашей оригинальной одномерной структуре данных для той же информации! Вы можете передать его функции, которая имеет дело только с одной строкой таблицы, вы можете легко отсортировать строки $myArray и т. Д.

Если бы вы указали свои индексы в обратном порядке, вы не сможете восстановить свои индивидуальные записи. Нет никакой «срезовой» нотации, которая может дать вам целую «колонку» двумерного массива.

Теперь для более широкой перспективы:

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

C имеет реальные двумерные массивы и массивы указателей. Массивы указателей работают точно так же, как в PHP (хотя допускаются только числовые индексы), и по той же причине: основной индекс выбирает из массива указателей, а младший индекс – просто индекс массива с указателем. Двумерные массивы C работают одинаково: основной индекс находится слева, а смежные местоположения в памяти отличаются на одно значение второстепенного (второго) индекса (за исключением, конечно, в конце строки). Это делает их совместимыми с массивами указателей, поскольку позволяет ссылаться на строку двумерного массива с использованием одного индекса. Например, a[0] является abcd :

  a[.][0] a[.][1] a[.][2] a[.][3] a[0]: abcda[1]: efg . a[2]: . . . . a[3]: . . . . 

Система работает без сбоев, потому что основной (строковый) индекс является первым. Fortran имеет реальные двумерные массивы, но имеет главный индекс справа: смежные местоположения в памяти отличаются на одно значение индекса слева (первым). Я обнаружил, что это боль в шее, так как нет подвыражения, которое одинаково сводится к одномерному массиву. (Но у меня есть фон C, поэтому я, конечно, предубежден).

Короче: вы делаете это правильно, и это, вероятно, не случайно, а потому, что вы узнали, глядя на хорошо написанный код.

С моей точки зрения, это не вопрос о соглашениях об именах массивов, а о том, как структурировать ваши данные. Значение: какие части информации принадлежат друг другу – и почему? Чтобы ответить на этот вопрос, вам нужно посмотреть как на читаемость, так и на производительность.

С точки зрения разработчика Java (и вы отметили вопрос также для Java), я не являюсь другом многомерных массивов, поскольку они, как правило, приводят к склонности к ошибкам в акробатике в огромных количествах вложенных for-loops. Чтобы избавиться от второго измерения в вашем массиве, можно создать дополнительные объекты, которые содержат информацию одного столбца.

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

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

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

В PHP, как ассоциативные массивы:

 $owner = array( 'year' => 2012, 'month' => 'July', 'measure' => 3 ); 

В C #, как хэш-таблицы :

 Hashtable owner = new Hashtable(); owner.Add("year", 2012); owner.Add("month", "July"); owner.Add("measure", 3); 

В Java, как хеш-таблицы:

 Hashtable owner = new Hashtable(); owner.put("year", new Integer(2012)); owner.put("month", new String("July")); owner.put("measure", new Integer(3)); 

В C # / Java, как объекты:

 public class Owner { public int year; public string month; public int measure; } Owner o = new Owner(); o.year = 2012; o.month = "July"; o.measure = 3; 

В C # и Java преимущество использования объектов над хэш-таблицами заключается в том, что для каждого поля / переменной могут быть объявлены типы переменных (т. Е. Int или string), что поможет предотвратить ошибки и сохранить целостность данных, поскольку будут выброшены ошибки (или будут генерироваться предупреждения), когда вы пытаетесь назначить неверный тип данных в поле.

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

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

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

Следующий пример PHP использует PDO и fetchAll для получения информации из базы данных:

 $sth = $dbh->prepare("SELECT year, month, measure FROM owners"); $sth->execute(); $rows = $sth->fetchAll(PDO::FETCH_ASSOC); $data = array(); foreach ($rows as $row) { $year = $row['year']; $month = $row['month']; if (!isset($data[$year])) { $data[$year] = array(); } if (!isset($data[$year][$month])) { $data[$year][$month] = array(); } array_push($data[$year][$month], $row); } 

Пример того, как эти данные могут выглядеть как код:

 $data = array( 2011 => array( 'July' => array( array('year' => 2011, 'month' => 'July', 'measure' => 1), array('year' => 2011, 'month' => 'July', 'measure' => 3) ), 'May' => array( array('year' => 2011, 'month' => 'May', 'measure' => 9), array('year' => 2011, 'month' => 'May', 'measure' => 4), array('year' => 2011, 'month' => 'May', 'measure' => 2) ) ), 2012 => array( 'April' => array( array('year' => 2012, 'month' => 'April', 'measure' => 7) ) ) ); 

Затем вы можете получить доступ к данным с помощью клавиш.

 $data[2011]['July']; // array( // array('year' => 2011, 'month' => 'July', 'measure' => 1), // array('year' => 2011, 'month' => 'July', 'measure' => 3) // ) 

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

Я очень редко использую массивы на Java, и то же самое относится к C #. Это объектно-ориентированные языки, и вы, как правило, получаете гораздо лучшую гибкость в долгосрочной перспективе, если вы используете классы и объекты вместо примитивных конструкций, таких как массивы.

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

Похоже, вы хотите получать разные типы в зависимости от того, что вы ищете? Месяц – это String, year – Integer и т. Д. Это делает массив или HashMap плохим выбором, потому что вызывающий код должен будет угадать тип данных, которые он извлекает. Лучшим вариантом было бы обернуть эти данные в объект, который будет безопасным по типу. В этом и заключается суть использования Java и C #.

В этом случае использование объекта даст вам гибкость, чтобы проверить, действительно ли месяц является реальной стоимостью. Например, вы можете создать перечисление, содержащее месяцы, и вернуть экземпляр этого метода getMonth.

Кроме того, у меня не хватает комментариев, чтобы оставить комментарий, но я хотел ответить на ответ Дэйва Ф.. Hashtable – это унаследованный класс из первых дней Java, поэтому его следует избегать. HashMap – рекомендуемая замена, оба реализуют интерфейс Map.

В ранние дни Java классы коллекции были синхронизированы, чтобы сделать их потокобезопасными (Vector, Hashtable и т. Д.). Это сделало эти основные классы необоснованно медленными и затрудняло работу. Если вам нужна синхронизированная карта в эти дни, есть оболочка для HashMap.

 Map m = Collections.synchronizedMap(new HashMap(...)); 

Другими словами, нет смысла использовать Hashtable больше, если вы не работаете с устаревшим кодом.

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

Пример: C использует row-major, что является обычным способом его выполнения. Когда вы перебираете массив N x N по строкам, вы, вероятно, будете иметь доступ только к памяти N раз, потому что каждая строка загружается вместе. Итак, для первого элемента первой строки вы выйдете в память и вернете всю строку. Для второго элемента первой строки вам не нужно будет выходить в память, потому что строка уже загружена. Однако, если вы решили пойти по столбцу, могут возникнуть проблемы с памятью. Для первого элемента первого столбца вы загрузите всю строку, затем для второго элемента первого столбца вы загрузите следующую строку … и т. Д. После того, как вы закончите пространство в кеше, первое строка, вероятно, будет отброшена, чтобы освободить место, и как только вы начнете загружать все элементы в столбце 2, вам придется начинать все заново. Это не проблема в Fortran; скорее, вы захотите сделать это так, потому что весь столбец загружается сразу, а не вся строка. Надеюсь, это имело смысл. См. Статью Википедии, которую я связал выше, для более наглядного объяснения.

Для большинства программ самым приоритетным разработчиком должен быть чистый код. Но знание того, как этот язык обрабатывает память, может быть существенным в тех случаях, когда производительность является ключевой. Хороший вопрос.