Сортировать многомерный массив объектов в столбцы - PullRequest
0 голосов
/ 17 января 2020

Я просто не могу понять это.

var arr = [
[ {'value': 3, 'id': 'ab'},  {'value': 1, 'id': 'ab'},  {'value': 5, 'id': 'ab'} ],
[ {'value': 6, 'id': 'bc'},  {'value': 3, 'id': 'bc'},  {'value': 4, 'id': 'bc'} ],
[ {'value': 1, 'id': 'cd'},  {'value': 3, 'id': 'cd'},  {'value': 2, 'id': 'de'} ],
]

У меня есть массив обр. arr [0], arr [1] и arr [2] содержат одинаковое количество объектов.

Я бы хотел отсортировать весь массив по arr [1]. Например,

var result = [
[ {'value': 1, 'id': 'ab'},  {'value': 5, 'id': 'ab'}, {'value': 3, 'id': 'ab'}, ],
[ {'value': 3, 'id': 'bc'},  {'value': 4, 'id': 'bc'}, {'value': 6, 'id': 'bc'}, ],
[ {'value': 3, 'id': 'cd'},  {'value': 2, 'id': 'de'}, {'value': 1, 'id': 'cd'}, ],
]

-> arr [1] теперь сортируется по значению (3,4,6). Соответствующие значения в arr [0] и arr [2] также были «отсортированы». Если arr [1] [1] перемещается в начало из-за правильной сортировки arr [1], то arr [0] [1] и arr [2] [1].

До сортировки

3 1 5
6 3 4
1 3 2

После сортировки

1 5 3 <- 1 is 'linked' to 3 in 2nd row, 5 is 'linked' to 4 in 2nd row, etc.
3 4 6 <- sorted
3 2 1 <- 3 is 'linked' to 3 in 2nd row, 2 is 'linked' to 4 in 2nd row, etc.

Например, я могу отсортировать arr [1], используя

arr[1].sort(function(a,b) {
    return a.value-b.value
});

, но, конечно, это не меняет arr [0] и обр [2], как я хотел бы. Очевидно, то же самое верно для

arr.forEach(item =>
item.sort(function(a,b) {
    return a.value-b.value
}));

, который сортирует только каждый массив отдельно.

Возможно, например, чтобы получить индексы a и b, чтобы я мог перемещать элементы в arr [0 ] и arr [1] сам?

Любая помощь очень ценится!

Ответы [ 2 ]

0 голосов
/ 19 января 2020

Вот метод, который сначала вычисляет порядок сортировки объектов.
Затем использует этот порядок сортировки для сортировки каждой строки одинаковым образом.

var arr = [
  [ {'value': 3, 'id': 'ab'}, {'value': 1, 'id': 'ab'}, {'value': 5, 'id': 'ab'} ],
  [ {'value': 6, 'id': 'bc'}, {'value': 3, 'id': 'bc'}, {'value': 4, 'id': 'bc'} ], 
  [ {'value': 1, 'id': 'cd'}, {'value': 3, 'id': 'cd'}, {'value': 2, 'id': 'de'} ]
];

function sortArrayColumnsByIndex(arr2dOfObj, rowindex, objkey) {
    let rownum = rowindex || 0;
    let key = objkey || Object.keys(arr2dOfObj[0][0])[0];
    let sortorder = arr2dOfObj[rownum]
         .map((x,i)=>[x,i])
         .sort((a, b) => a[0][key] < b[0][key] ? -1 : a[0][key] > b[0][key] ? 1 : 0) 
         .map(x=>x[1]);

    arr2dOfObj.forEach( 
       (row, idx) => {
       let sorted = [];
       sortorder.forEach( (y) => {
         sorted.push(row[y]);
       })
       arr2dOfObj[idx] = sorted;
      }
  );
}

sortArrayColumnsByIndex(arr, 1, 'value');

console.log(JSON.stringify(arr))
0 голосов
/ 18 января 2020

Возможно, это не самое элегантное решение, но я транспонирую массив, затем сортирую его и затем возвращаю обратно в исходную форму.

// sort array accordingly to this row
let i = 1;

var arr = [
[ {'value': 1, 'id': 'ab'},  {'value': 6, 'id': 'ab'},  {'value': 3, 'id': 'ab'} ],
[ {'value': 3, 'id': 'bc'},  {'value': 1, 'id': 'bc'},  {'value': 4, 'id': 'bc'} ],
[ {'value': 2, 'id': 'cd'},  {'value': 1, 'id': 'cd'},  {'value': 8, 'id': 'cd'} ],
]

function transpose(m) {
    return Object.keys(m[0]).map(function(a) {
        return m.map(function(b) { return b[a]; });
    });
}

arr = transpose(arr);

arr.sort(function sortFunction(a, b) {
    if (a[i].value === b[i].value) {
        return 0;
    }
    else {
        return (a[i].value < b[i].value) ? -1 : 1;
    }
})

arr = transpose(arr);

console.log(arr);

...