Стиль SQL JOIN для данных JSON - PullRequest
16 голосов
/ 31 августа 2011

Есть ли способ эффективно объединить данные JSON?Предположим, у нас есть два набора данных JSON:

{"COLORS":[[1,red],[2,yellow],[3,orange]]}

{"FRUITS":[[1,apple],[2,banana],[3,orange]]}

И я хочу превратить это в следующую клиентскую сторону:

{"NEW_FRUITS":[[1,apple,red],[2,banana,yellow],[3,orange,orange]]}

Имейте в виду, что здесь будут тысячи записей со значительносложные структуры данных.JQuery и ванильный JavaScript оба в порядке.Также имейте в виду, что могут быть цвета без фруктов и фрукты без цветов.

ПРИМЕЧАНИЕ. Для простоты предположим, что оба набора данных расположены в одном порядке, но во втором наборе данных могут быть пробелы.

Ответы [ 3 ]

8 голосов
/ 31 августа 2011

Тот факт, что будут тысячи входов, а ключи не обязательно упорядочены, означает, что ваша лучшая ставка (по крайней мере, для крупных объектов) - сначала отсортировать по ключу.Для объектов размером менее 5 или около того достаточно подхода грубой силы n ^ 2.

Затем вы можете записать результат, пройдя параллельно два массива, добавив новые «записи» вваш вывод, как вы идете.Эта идея сортировки-затем-слияния является относительно мощной и часто используется.Если вы не хотите сначала выполнять сортировку, вы можете добавлять элементы в очередь с приоритетами, объединяя их по мере продвижения.Подход сортировки-затем-слияния, возможно, концептуально проще для кодирования;если производительность имеет значение, вы должны выполнить некоторое профилирование.

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

ADDENDUM Я также поиграл:1011 * Он не делает никаких предположений о порядке клавиш и никаких предположений относительно относительной длины массивов.Единственными предположениями являются имена полей и тот факт, что каждый подмассив имеет два элемента.

8 голосов
/ 16 декабря 2014

Alasql Библиотека JavaScript JavaScript делает именно то, что вам нужно, в одну строку:

 <script src="alasql.min.js"></script>
 <script>
    var data = { COLORS: [[1,"red"],[2,"yellow"],[3,"orange"]],            
                 FRUITS: [[1,"apple"],[2,"banana"],[3,"orange"]]};

    data.NEW_FRUITS = alasql('SELECT MATRIX COLORS.[0], COLORS.[1], FRUITS.[1] AS [2] \
         FROM ? AS COLORS JOIN ? AS FRUITS ON COLORS.[0] = FRUITS.[0]',
         [data.COLORS, data.FRUITS]);
 </script>

Вы можете поиграть с в этом примере в jsFiddle.

Это выражение SQL, где:

  • SELECT - оператор выбора
  • MATRIX - модификатор, который преобразует набор результатов из массива объектов в массив массивов
  • ЦВЕТА. [0]- первый столбец массива COLORS и т. д.
  • FRUITS. 1 AS 2 - второй столбец массива FRUITS будет сохранен как третий столбец в результирующем наборе записей
  • ОТ?AS COLORS - массив данных из параметров с именем COLOURS в операторе SQL
  • JOIN?ON ... - объединить
  • [data.COLORS, data.FRUITS] - параметры с массивами данных
3 голосов
/ 31 августа 2011

Прямого пути нет, но вы можете написать логику для получения комбинированного объекта, подобного этому.Поскольку "apple, red, banana ...." - все строки, они должны быть заключены в одинарные или двойные кавычки.

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

Работа демо

var colors = {"COLORS":[[1,'red'],[2,'yellow'],[3,'orange']]}

var fruits = {"FRUITS":[[1,'apple'],[2,'banana'],[3,'orange']]}

var newFruits = {"NEW_FRUITS": [] }

//Just to make sure both arrays are the same size, otherwise the logic will break
if(colors.COLORS.length == fruits.FRUITS.length){
    var temp;
    $.each(fruits.FRUITS, function(i){
        temp = this;
        temp.push(colors.COLORS[i][2]);
        newFruits.NEW_FRUITS.push(temp);
    });
}

В качестве альтернативы, если вы можете создать colors и fruits конфиги в виде массива объектов, вместо массива массивов, вы можете попробовать это решение.Последовательность элементов здесь не имеет значения, но размер массива все равно должен совпадать.

Рабочая демо

var colors = {"COLORS":[ {"1": 'red'}, { "2": 'yellow'}, {"3":'orange'}]}

var fruits = {"FRUITS":[ {"1":'apple'}, { "2": 'banana'}, {"3":'orange'}]}

var newFruits = {"NEW_FRUITS": [] }

if(colors.COLORS.length == fruits.FRUITS.length){
    var temp, first;
    $.each(fruits.FRUITS, function(i){
        for(first in this)break;
        temp = {};
        temp[first] = [];
        temp[first].push(this[first]);
        temp[first].push(colors.COLORS[i][first]);
        newFruits.NEW_FRUITS.push(temp);
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...