Javascript-сортировка массива на основе другого массива



можно ли сортировать и переставлять массив, который выглядит так:



itemsArray = [ 
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]


чтобы соответствовать расположению этого массива:



sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]


к сожалению, у меня нет никаких идентификаторов для отслеживания. Мне нужно будет приоритет элементов-массив, чтобы соответствовать sortingArr как можно ближе.



обновление:



вот результат, который я ищу:



itemsArray = [    
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]


есть идеи, как это можно сделать?

961   14  

14 ответов:

что-то типа:

items = [ 
    ['Anne', 'a'],
    ['Bob', 'b'],
    ['Henry', 'b'],
    ['Andrew', 'd'],
    ['Jason', 'c'],
    ['Thomas', 'b']
]

sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []

sorting.forEach(function(key) {
    var found = false;
    items = items.filter(function(item) {
        if(!found && item[1] == key) {
            result.push(item);
            found = true;
            return false;
        } else 
            return true;
    })
})

result.forEach(function(item) {
    document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})

вот более короткий код, но он уничтожает sorting время:

result = items.map(function(item) {
    var n = sorting.indexOf(item[1]);
    sorting[n] = '';
    return [n, item]
}).sort().map(function(j) { return j[1] })

одна строка ответа.

itemsArray.sort(function(a, b){  
  return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});

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

поэтому, если я правильно понимаю пример, который вы даете, вы можете сделать что-то вроде:

function sortFunc(a, b) {
  var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
  return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}

itemsArray.sort(sortFunc);

Случай 1: Исходный Вопрос (Без Библиотек)

много других ответов, которые работают. :)

Случай 2: Оригинальный Вопрос (Лодаш.js или подчеркивание.js)

var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });

Случай 3: сортировка Array1, как если бы это был Array2

Я предполагаю, что большинство людей пришли сюда, ища эквивалент PHP array_multisort (я сделал), поэтому я подумал, что также опубликую этот ответ. Есть несколько вариантов:

1. Есть существующая JS выполнение функция array_multisort(). Спасибо @Adnan за указание на это в комментариях. Однако он довольно большой.

2. Написать свой. (демо JSFiddle)

function refSort (targetData, refData) {
  // Create an array of indices [0, 1, 2, ...N].
  var indices = Object.keys(refData);

  // Sort array of indices according to the reference data.
  indices.sort(function(indexA, indexB) {
    if (refData[indexA] < refData[indexB]) {
      return -1;
    } else if (refData[indexA] > refData[indexB]) {
      return 1;
    }
    return 0;
  });

  // Map array of indices to corresponding values of the target array.
  return indices.map(function(index) {
    return targetData[index];
  });
}

3. Лодашь.js или подчеркивания.js (обе популярные, меньшие библиотеки, которые сосредоточены на производительности) предлагают вспомогательные функции, которые позволяют вам сделать это:

    var result = _.chain(sortArray)
      .pairs()
      .sortBy(1)
      .map(function (i) { return itemArray[i[0]]; })
      .value();

...Который будет (1) группировать sortArray в [index, value] пары, (2) сортировка они по значению (вы также можете предоставить обратный вызов здесь), (3) замените каждую из пар элементом из itemArray по индексу, из которого возникла пара.

это, вероятно, слишком поздно, но, вы также можете использовать некоторые измененные версии кода ниже в стиле ES6. Этот код предназначен для массивов типа:

var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];

фактическая операция :

arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));

фактическая операция в ES5:

arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
    return arrayToBeSorted.includes(v);
});

в результате arrayToBeSorted = [3,5]

не уничтожает массив ссылок.

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

function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
  var itemsMap = {};
  for (var i = 0, item; (item = itemsArray[i]); ++i) {
    (itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
  }
  return itemsMap;
}

function sortByKeys(itemsArray, sortingArr) {
  var itemsMap = createItemsMap(itemsArray), result = [];
  for (var i = 0; i < sortingArr.length; ++i) {
    var key = sortingArr[i];
    result.push([itemsMap[key].shift(), key]);
  }
  return result;
}

см.http://jsfiddle.net/eUskE/

var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
    var found = false;
    for(var j=0; j < itemsArray.length && !found; j++) {
        if(itemsArray[j][1] == sortingArr[i]) {
            sortedArray.push(itemsArray[j]);
            itemsArray.splice(j,1);
            found = true;
        }
    }
}

http://jsfiddle.net/s7b2P/

результирующий порядок: Боб, Джейсон, Генри, Томас, Энн, Эндрю

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

массив должен быть ссылочным массивом, тот, который вы хотите, чтобы второй массив был отсортирован по:

var columns = [
    {last_name: "last_name"},
    {first_name: "first_name"},
    {book_description: "book_description"},
    {book_id: "book_id"},
    {book_number: "book_number"},
    {due_date: "due_date"},
    {loaned_out: "loaned_out"}
];

Я сделал это как объекты, потому что они будут иметь другие свойства в конечном итоге.

создал массив:

 var referenceArray= [];
 for (var key in columns) {
     for (var j in columns[key]){
         referenceArray.push(j);
     }
  }

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

result.forEach((element, index, array) => {                            
    var tr = document.createElement('tr');
    for (var i = 0; i < referenceArray.length - 1; i++) {
        var td = document.createElement('td');
        td.innerHTML = element[referenceArray[i]];
        tr.appendChild(td);

    }
    tableBody.appendChild(tr);
}); 
let a = ['A', 'B', 'C' ]

let b = [3, 2, 1]

let c = [1.0, 5.0, 2.0]

// these array can be sorted by sorting order of b

const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))

const sortBy = (a, b, c) => {
  const zippedArray = zip([a, b, c])
  const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])

  return zip(sortedZipped)
}

sortBy(a, b, c)

используйте $.метод inArray () из jQuery. Тогда вы могли бы сделать что-то подобное

var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();

for(var i=sortingArr.length; i--;) {
 var foundIn = $.inArray(sortingArr[i], itemsArray);
 newSortedArray.push(itemsArray[foundIn]);
}

это должно работает:

var i,search, itemsArraySorted = [];
while(sortingArr.length) {
    search = sortingArr.shift();
    for(i = 0; i<itemsArray.length; i++) {
        if(itemsArray[i][1] == search) {
            itemsArraySorted.push(itemsArray[i]);
            break;
        }
    } 
}

itemsArray = itemsArraySorted;

Я делаю что-то вроде того, что вы просили, но мне нужен этот способ сортировки.это то, что я сделал для сортировки массива массивов на основе другого массива, это на^3 и не может быть лучшей практикой (ES6):

function sortArray(arr, arr1){
      return arr.map(item => {
        let a = [];
        for(let i=0; i< arr1.length; i++){
          for (const el of item) {
            if(el == arr1[i]){
              a.push(el);
            }   
            }
          }
          return a;
      });
    }
    
    const arr1 = ['fname', 'city', 'name'];
  const arr = [['fname', 'city', 'name'],
  ['fname', 'city', 'name', 'name', 'city','fname']];
  console.log(sortArray(arr,arr1));
Это может кому-то помочь

вы можете сделать что-то вроде этого:

function getSorted(itemsArray , sortingArr ) {
  var result = [];
  for(var i=0; i<arr.length; i++) {
    result[i] = arr[sortArr[i]];
  }
  return result;
}

вы можете проверить это здесь.

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

см. ссылке

см.

использовать пересечение двух массивов.

Ex:

var sortArray = ['a', 'b', 'c',  'd', 'e'];

var arrayToBeSort = ['z', 's', 'b',  'e', 'a'];

_.intersection(sortArray, arrayToBeSort) 

= > ['a',' b','e']

если 'z и' s ' находятся вне диапазона первого массива, добавьте его в конце результата

Comments

    Ничего не найдено.