localstorage: получить конкретное значение localstorage, которое содержит много элементов

#javascript #jquery #json #local-storage #stringify

#javascript #jquery #json #local-storage #stringify

Вопрос:

В localstorage у меня есть ключ «результаты» с этими значениями:

 [{"id":"item-1","href":"google.com","icon":"google.com"},
{"id":"item-2","href":"youtube.com","icon":"youtube.com"},
{"id":"item-3","href":"google.com","icon":"google.com"},
{"id":"item-4","href":"google.com","icon":"google.com"},
{"id":"item-5","href":"youtube.com","icon":"youtube.com"},
{"id":"item-6","href":"asos.com","icon":"asos.com"},
{"id":"item-7","href":"google.com","icon":"google.com"},
{"id":"item-8","href":"mcdonalds.com","icon":"mcdonalds.com"}]
  

Чтобы получить последний элемент, я использую это:

 // this is how I parse the arrays
var result = JSON.parse(localStorage.getItem("result")); 


for(var i=0;i<result.length;i  ) {
    var item = result[i];
    $('element').val(item.href);
}
  

Как я могу получить href для элемента-3 или для определенного идентификатора?

Ответ №1:

Использование встроенного Array.filter

Если вы ориентируетесь только на современные браузеры (IE9 или последнюю версию любого другого основного браузера), вы можете использовать метод массива JavaScript 1.6 filter .

 var testItem,
    data = [{"id":"item-1","href":"google.com","icon":"google.com"},
{"id":"item-2","href":"youtube.com","icon":"youtube.com"},
{"id":"item-3","href":"google.com","icon":"google.com"},
{"id":"item-4","href":"google.com","icon":"google.com"},
{"id":"item-5","href":"youtube.com","icon":"youtube.com"},
{"id":"item-6","href":"asos.com","icon":"asos.com"},
{"id":"item-7","href":"google.com","icon":"google.com"},
{"id":"item-8","href":"mcdonalds.com","icon":"mcdonalds.com"}];

function getItemById(data, id) {
    // filter array down to only the item that has the id
    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
    var ret = data.filter(function (item) {
        return item.id === id;
    });

    // Return the first item from the filtered array   
    // returns undefined if item was not found
    return ret[0];
}


testItem = getItemById(data, 'item-3');
  

Рабочий пример

Ручной цикл по данным

Если вы не можете использовать filter, вы, вероятно, застряли с простым использованием цикла:

 var testItem,
    data = [{"id":"item-1","href":"google.com","icon":"google.com"},
{"id":"item-2","href":"youtube.com","icon":"youtube.com"},
{"id":"item-3","href":"google.com","icon":"google.com"},
{"id":"item-4","href":"google.com","icon":"google.com"},
{"id":"item-5","href":"youtube.com","icon":"youtube.com"},
{"id":"item-6","href":"asos.com","icon":"asos.com"},
{"id":"item-7","href":"google.com","icon":"google.com"},
{"id":"item-8","href":"mcdonalds.com","icon":"mcdonalds.com"}];

function getItemById(data, id) {
    var i, len;
    for (i = 0, len = data.length; i < len; i  = 1) {
        if(id === data[i].id) {
            return data[i];
        }
    }

    return undefined;
}

testItem = getItemById(data, 'item-3');
  

Рабочий пример

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

Рефакторинг в объект вместо массива

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

 var data = {
    "item-1": {"href": "google.com", "icon": "google.com"},
    "item-2": {"href": "youtube.com", "icon": "youtube.com"},
    "item-3": {"href": "google.com", "icon": "google.com"},
    "item-4": {"href": "google.com", "icon": "google.com"},
    "item-5": {"href": "youtube.com", "icon": "youtube.com"},
    "item-6": {"href": "asos.com", "icon": "asos.com"},
    "item-7": {"href": "google.com", "icon": "google.com"},
    "item-8": {"href": "mcdonalds.com", "icon": "mcdonalds.com"}
};
  

Это сделало бы доступ к элементам еще проще и быстрее:

 var data = JSON.parse(localStorage.getItem("result")); 
data["item-3"].href;
  

Комментарии:

1. Привет и спасибо. В моем использовании я устанавливаю TestItem как JSON.parse(localStorage.GetItem(«результат»)). Когда я делаю это, все результаты не определены.

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

3. @jQuerybeast В исходном примере была просто установка тестовых данных, а затем доступ к ним через закрытие, я изменил его, чтобы использовать его в качестве параметра вместо этого. Затем вы могли бы вызвать его, передав ему данные: testItem = getItemById(JSON.parse(localStorage.getItem("result")), 'item-3'); . Если вам понадобится захватить более одного элемента, вам, вероятно, следует присвоить ему результаты JSON.parse(localStorage.getItem("result")) переменной вместо того, чтобы называть ее встроенной.

4. @Hugolpz вы склонны слишком сильно менять ответы. Вы меняете код, вы меняете значение. Я, например, никогда не одобрю эти изменения. Не буду спорить с вами по этому поводу, но мой личный совет — не делайте таких изменений. Не стесняйтесь исправлять грамматику и орфографию, но позвольте автору сообщения исправить код или изменить имена переменных или что-то еще. Не делайте этого самостоятельно.

5. @ShadowWizard: веб 2.0. Если это уточнение, лучшее уточнение, лучшая иерархическая сегментация, лучшая читаемость: давайте просто сделаем это.

Ответ №2:

для этого в jQuery есть вспомогательный фильтр:

 $(result).filter(function(){return this.id == "item-3";})[0]
  

Функция для href элемента с определенным идентификатором будет:

 function getItemHrefById(json, itemId){
    return json.filter(function(testItem){return testItem.id == itemId;})[0].href;
}
  

И пример использования:

 var href = getItemHrefById(result, "item-3");
  

Вы можете увидеть рабочий пример на http://jsfiddle.net/LXvLB /

Обновить

Если вы не можете прочитать элемент из локального хранилища, возможно, вы забыли вызвать JSON.stringify при установке значения:

 localStorage["results"] = JSON.stringify([{"id":"item-1","href":"google.com","icon":"google.com"}, 
{"id":"item-2","href":"youtube.com","icon":"youtube.com"}, 
{"id":"item-3","href":"google.com","icon":"google.com"}, 
{"id":"item-4","href":"google.com","icon":"google.com"}, 
{"id":"item-5","href":"youtube.com","icon":"youtube.com"}, 
{"id":"item-6","href":"asos.com","icon":"asos.com"}, 
{"id":"item-7","href":"google.com","icon":"google.com"}, 
{"id":"item-8","href":"mcdonalds.com","icon":"mcdonalds.com"}])
  

Для правильной сериализации вам необходимо преобразовать json в строку (и использовать JSON.parse для получения JSON обратно)

Это последний пример.

Редактировать

Как указывал бесполезный код, этот метод существенно медленнее, чем встроенная функция filter (и пользовательский цикл, но я думаю, что введение нескольких новых строк кода для экономии 20-30 мс является излишеством, если производительность не является проблемой), поэтому я обновляю свой пример, чтобы не использовать jquery filter. 1, пожалуйста, за его ответ на это.

Также, что важно отметить здесь, если бы в этом массиве были сотни закладок вместо 8, цикл for, вероятно, был бы статистически примерно в два раза быстрее (поскольку ему не нужно выполнять итерации по остальной части массива). Но в этом случае, вероятно, было бы хорошей идеей поместить цикл for в функцию, которая возвращает первый найденный элемент, удовлетворяющий условию, и с prototypejs его, вероятно, можно даже подключить к array.

Комментарии:

1. Какой из них я использую где? Похоже, у меня это не работает … и это тоже не имеет смысла. getItemById не является переменной?

2. Метод jQuery .filter() используется для фильтрации узлов DOM, а не данных JSON или массивов.

3. @jQuerybeast извините, мой пример был ошибочным, вам нужно вызвать созданную мной функцию, а не getItemById, я исправил пример и добавил ссылку jsfiddle, чтобы вы могли видеть использование.

4. @Бесполезный-код по предоставленной вами ссылке: «описание фильтра: уменьшите набор сопоставленных элементов до тех, которые соответствуют селектору, или передайте тест функции». Набор сопоставляемых элементов в данном случае представляет собой массив json. Ничто не мешает вам использовать его для этого.

5. @GoranObradovic «Набор сопоставленных элементов» относится к элементам DOM, которые были сопоставлены селектором при создании объекта jQuery. jQuery будет принимать объекты, отличные от DOM, и это достаточно общая ситуация, которую вы можете использовать для фильтрации универсального массива, но на самом деле это не предназначено для фильтрации универсальных массивов. В любом случае, создание экземпляра jQuery создает много ненужных излишеств. Этот метод намного медленнее, чем использование пользовательского цикла, который возвращается, как только находит элемент, который он ищет, или Array.prototype.filter() . Сравнение скорости здесь: jsfiddle.net/53v3G

Ответ №3:

для метода jquery filter, я думаю, использование функции обратного вызова и привязка параметра поиска более элегантны и удобочитаемы:

 function filterById(id, i, obj) {
    return obj.id === id;
}

function getItemHrefById(json, itemId) {
    return $(json).filter(filterById.bind(null, itemId))[0].href;
}
  

обычная скрипка

(тем не менее, я предпочитаю подход «для цикла» для этого !!)