Лучшая структура данных или алгоритм, чем итеративный поиск в многомерных массивах для поиска соответствующих значений? - PullRequest
1 голос
/ 30 сентября 2011

Для сайта, над которым я работаю, я использую библиотеку, чтобы получить список состояний.Он возвращает численно индексированный массив состояний, каждый из которых имеет три ключа: stateCode, stateName и stateSeg.Это выглядит так:

array
  0 => &
    array
      'stateCode' => string 'AL' (length=2)
      'stateName' => string 'Alabama' (length=7)
      'stateSeg' => string 'alabama-al' (length=10)
  1 => &
    array
     'stateCode' => string 'AK' (length=2)
      'stateName' => string 'Alaska' (length=6)
      'stateSeg' => string 'alaska-ak' (length=9)
  2 => &
    array
      'stateCode' => string 'AZ' (length=2)
      'stateName' => string 'Arizona' (length=7)
      'stateSeg' => string 'arizona-az' (length=10)

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

foreach ($this->data['stateList'] as $state)
{
    if ($state['stateCode'] == $searchParams['state'])
    {
        $stateSeg = $state['stateSeg'];
        break;
    }
}
$url = BASEURL . '/' . $stateSeg . ".html";

Мне это кажется неэффективным.Я думаю, что наиболее эффективное решение, которое я смог придумать, состоит в том, чтобы превратить состояния в объекты и поместить их в массив с несколькими ключами для stateCode, stateSeg и stateName, каждый из которых указывает на один и тот же объект состояния, поэтому на них можно ссылаться какэто:

stateList[‘CA’]->getStateSeg();

или

stateList[‘Arizona’]->getStateCode();

или

stateList[‘alaska-ak’]->getStateName();

и т. д.

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

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

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

Ответы [ 4 ]

1 голос
/ 30 сентября 2011

Если php поддерживает ссылки, и я знаю состояние, я просто передаю ссылку на соответствующий элемент массива и извлекаю из него необходимое поле.

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

Кроме того, мне интересно, могли бы вы избавиться от всего, кроме строк "Аляска-Ак". Данные выглядят крайне избыточными.

0 голосов
/ 30 сентября 2011

Мне это кажется неэффективным

Это не так. Даже в худшем случае, итерация по 50 элементам, вероятно, на порядок быстрее, чем запрос дБ.

библиотека для получения списка состояний

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

Данные несколько избыточны ... Все, что вам нужно, это два элемента: код штата и название штата. Вы можете построить "государственный сегмент" из этих двух. Поэтому держите карту кодов штатов и карту названий штатов.

0 голосов
/ 30 сентября 2011

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

array
  0 => &
    array
      'stateCode' => string 'AL' (length=2)
      'stateName' => string 'Alabama' (length=7)
      'stateSeg' => string 'alabama-al' (length=10)
  1 => &
    array
     'stateCode' => string 'AK' (length=2)
      'stateName' => string 'Alaska' (length=6)
      'stateSeg' => string 'alaska-ak' (length=9)
  2 => &
...

Каждый объект состояния имеет идентификатор, ключ массива: 0, 1, 2, ....

Все, что вам нужно сделать, этосоздать три индекса на основе ключа.Вы используете значение в качестве ключа (например, «AL» для индекса «stateCode»), а в качестве значения вы берете индекс массива, 0:

$indexStateCode['AL'] = 0;

После этого вы уже можете быстро найти это:1010 *

Инкапсулируйте это в класс с помощью ArrayAccess , а затем по запросу создайте экземпляр объекта состояния.Вам не нужно раньше.

0 голосов
/ 30 сентября 2011

Не могли бы вы сохранить состояния в таблице mysql / sqlite и использовать механизм базы данных для поиска?

...