Как перебрать массив объектов в JavaScript? - PullRequest
1 голос
/ 25 июня 2010

Я использую PHP для извлечения «заданий» из моей базы данных и кодирую его как JSON. Когда я передаю данные в javascript, я получаю что-то вроде этого:

Array {
   [0] => Task {
      id: 2,
      name: 'Random Task',
      completed: 0
   }
   [1] => Task {
      id: 8,
      name: 'Another task',
      completed: 1
   }
}

и т.д.

Полагаю, мой настоящий вопрос в том, как наиболее эффективно найти задачу по ее идентификатору? Итерация по массиву и проверка каждого объекта может показаться не самым эффективным? Есть ли другой способ сделать это?

Ответы [ 6 ]

6 голосов
/ 25 июня 2010

Суть объектов Javascript в том, что они являются важными картами. Вы можете получить доступ к свойствам, используя как точечную нотацию ("object.property"), так и индексную нотацию ("object [" property "]). Вы также можете перечислить через ее свойства, используя for (i ...) или (в ...)

for (var i = 0; i < arrayObj.length; i++) { ... }

for (var prop in arrayObj) { ... }

То, что я делал недавно, - это создание некоторых расширений Linq-esque для объекта массива:

Array.prototype.Where = function(predicate) {
    Throw.IfArgumentNull(predicate, "predicate");
    Throw.IfNotAFunction(predicate, "predicate");

    var results = new Array();
    for (var i = 0; i < this.length; i++) {
        var item = this[i];
        if (predicate(item))
            results.push(item);
    }

    return results;
};

Игнорируя мой собственный тип Броска, он в основном позволяет вам делать что-то вроде:

var item = arrayObj.Where(function(i) { return (i.id == 8); }).FirstOrDefault();

Я опубликую все это в какой-то момент, если вам интересно?

2 голосов
/ 25 июня 2010

Еще немного пищи для размышлений, вот чем я закончил:

this.find = function (test) {
    var results = [];
    for (var i = 0,l = this.tasks.length; i < l; i++) {
        var t = this.tasks[i];
        if (eval(test)) {
            results.push(this.tasks[i]);
        }
    }
    return results;
}

это позволяет мне выполнять простые задачи. Поиск ('t.id == 2') или задачи.find ('t.completed == 1');

2 голосов
/ 25 июня 2010

Если вам не нужно поддерживать порядок, то лучше всего использовать обычный объект и индексировать по идентификатору задачи.Это дает вам O(1) доступ.

var tasks = {
   '2': {
      id: 2,
      name: 'Random Task',
      completed: 0
   },
   ...
}

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

// internal API (to help maintain order)
taskIDs = [a, b, c, ..];
// internal API (for actual storage)
tasks = {
    a: { .. },
    b: { .. },
};

// external API for iterating objects in order
forEach(fn);
// external API for accessing task by ID
get(id);

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

Если вам нужна ссылка для реализации такого класса, см. source для LinkedMap из библиотеки Google Closure.

2 голосов
/ 25 июня 2010

Обычно наиболее эффективный способ перебора коллекции массивов в Javascript - это придерживаться нативного цикла for. Причина, по которой я говорю «обычно», заключается в том, что реализация сводится к реализации каждого уникального браузера в javascript, поэтому нет абсолютного окончательного ответа.

Есть хороший пост в http://solutoire.com/2007/02/02/efficient-looping-in-javascript/, который описывает производительность каждого из основных методов итерации и опытным путем приходит к тому же выводу.

0 голосов
/ 25 июня 2010

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

Если он большой, вы должны вместо этого вернуть словарь (как прокомментировал Мэтью Флэшен), в котором в качестве ключа используется идентификатор задачи. Таким образом, вы получите постоянный поиск по времени (по крайней мере, если реализация javascript оптимальна).

Просто используйте обычный ассоциативный массив PHP и запустите его через json_encode или что-то еще, что вы используете.

//Assume you have your original Array named $tasks:
$dictionary = Array();
foreach($tasks as $task)
    $dictionary[$task->getID()] = $task;
0 голосов
/ 25 июня 2010

Если идентификатор уникален (и в основном непрерывен), вы можете выполнить однократную перестановку массива, чтобы индекс массива отражал идентификатор.Если они не уникальны, вы можете отсортировать их и выполнить бинарный поиск.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...