Как отсортировать вложенный массив по нескольким значениям в JavaScript

#javascript #node.js #reactjs #typescript

Вопрос:

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

 [  {  "modelId":1,  "modelCode":"model1",  "price":[  {  "PRICE_CODE1":225.01  },  {  "PRICE_CODE2":247.68  },  {  "PRICE_CODE3":298.0  }  ]  },  {  "modelId":2,  "modelCode":"model2",  "price":[  {  "PRICE_CODE1":100.01  },  {  "PRICE_CODE2":200.68  },  {  "PRICE_CODE3":300.0  }  ]  } ]  

Ожидаемый Результат:

 [  {  "modelId":2,  "modelCode":"model2",  "price":[  {  "PRICE_CODE1":100.01  },  {  "PRICE_CODE2":200.68  },  {  "PRICE_CODE3":300.0  }  ]  },  {  "modelId":1,  "modelCode":"model1",  "price":[  {  "PRICE_CODE1":225.01  },  {  "PRICE_CODE2":247.68  },  {  "PRICE_CODE3":298.0  }  ]  } ]  

в соответствии с приведенным выше примером сортировка-это PRICE_CODE1, код модели в порядке возрастания. Я использую следующий запрос-

 function sortByMultipleKey(keys) {  return function(a, b) {  if (keys.length == 0) return 0; // force to equal if keys run out  key = keys[0]; // take out the first key  if (a[key] lt; b[key]) return -1; // will be 1 if DESC  else if (a[key] gt; b[key]) return 1; // will be -1 if DESC  else return sortByMultipleKey(keys.slice(1))(a, b);  } } arr.sort(sortByMultipleKey(['PRICE_CODE1','modelCode']))  

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

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

1. какое значение вы принимаете для сравнения?

2. PRICE_CODE1, код модели

3. который PRICE_CODE1 ?

4. в приведенном выше JSON PRICE_CODE1 является ключом внутри массива цен. сравнение объекта один

5. да, я знаю. но какой из них вы берете для сравнения объекта один и два?

Ответ №1:

Внимание: Это будет работать для структуры массива цен, которая у вас есть, но не для кода модели в качестве ключа сортировки.

 const data = [  {  "modelId":2,  "modelCode":"model2",  "price":[  {  "PRICE_CODE1":100.01  },  {  "PRICE_CODE2":200.68  },  {  "PRICE_CODE3":300.0  }  ]  },  {  "modelId":1,  "modelCode":"model1",  "price":[  {  "PRICE_CODE1":225.01  },  {  "PRICE_CODE2":247.68  },  {  "PRICE_CODE3":298.0  }  ]  } ]  function sortData(sortKeys = []) {  data.sort((a,b) =gt; {  for (let sortKey of sortKeys) {  const priceObjA = a.price.find(x =gt; sortKey in x);  const priceObjB = b.price.find(x =gt; sortKey in x);  const priceA = priceObjA amp;amp; priceObjA[sortKey] || 0;  const priceB = priceObjB amp;amp; priceObjB[sortKey] || 0;  const result = priceA - priceB;  if (result !== 0) {  return result;  }  }  // fallback for equality  return 0;  }) }   sortData(['PRICE_CODE1']); console.log(JSON.stringify(data,null,2));  sortData(['PRICE_CODE2']); console.log(JSON.stringify(data,null,2));  sortData(['PRICE_CODE3']); console.log(JSON.stringify(data,null,2)); 

Ответ №2:

arr.сортировка(sortByMultipleKey([‘PRICE_CODE1′,’Код модели’]))

Ваш sortByMultipleKey берет список ключей, каждый из которых описывает один ключ. Это не может описать PRICE_CODE1 поле объекта под prices .

По сути, вы пытаетесь придумать синтаксис для описания произвольного расположения в иерархических данных.

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

Ниже я определю 2 функции. Первый извлечет первый PRICE_CODE1 из элементов prices .

 function(d) {  for (i = 0; i lt; d.price.length; d  ) {  if ("PRICE_CODE1" in d.price[i]) {  return d.price[i].PRICE_CODE1  }  }  return undefined  }  

Один для кода модели проще:

 function(d) {  return d.modelCode  }  

Я также добавляю 3-ю модель с тем же PRICE_CODE1 самым, чтобы это modelCode также было актуально.

 function sortByMultiple(field_funcs) {  return function(a, b) {  for (i = 0; i lt; field_funcs.length; i  ) {  fa = field_funcs[i](a)  fb = field_funcs[i](b)  console.log("Comparing "   fa   " and "   fb)  if (fa lt; fb) return -1;  if (fa gt; fb) return 1;  if (i   1 == field_funcs.length) return 0  }  } } var data = [{  "modelId": 2,  "modelCode": "model2",  "price": [{  "PRICE_CODE1": 100.01  },  {  "PRICE_CODE2": 200.68  },  {  "PRICE_CODE3": 300.0  }  ]  },  {  "modelId": 1,  "modelCode": "model1",  "price": [{  "PRICE_CODE1": 225.01  },  {  "PRICE_CODE2": 247.68  },  {  "PRICE_CODE3": 298.0  }  ]  },  {  "modelId": 3,  "modelCode": "model3",  "price": [{  "PRICE_CODE1": 225.01  },  {  "PRICE_CODE2": 247.68  },  {  "PRICE_CODE3": 298.0  }  ]  } ]  data.sort(sortByMultiple([  function(d) {  for (i = 0; i lt; d.price.length; d  ) {  if ("PRICE_CODE1" in d.price[i]) {  return d.price[i].PRICE_CODE1  }  }  return undefined  },  function(d) {  return d.modelCode  } ])) console.log(data) 

Ответ №3:

Вы можете использовать библиотеку lodash:

 _.orderBy( data, [c =gt; c.price[0].PRICE_CODE1, "modelCode"], ["asc", "asc"]);  

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

1. Эй, тебе не кажется, что это сначала разберется с wrt PRICE_CODE1 , а затем с wrt modelCode . Наконец, по вашему методу массив будет отсортирован только на основе last parameter , предыдущая сортировка не будет иметь никакого эффекта.

2. Привет, Химаншу, Ты прав. Он модифицирован.