Задать вопрос
@Ji00

Как отсортировать часть массива?

Дан такой массив [2, “No”, 6, 8, “”, 1, “No”, “”, 10] . Вопрос: как отсортировать массив так что бы все пустые и содержащие не цифры строки остались на своих местах, а все цифры сортировались по убыванию.
Пример нужного результата: [10, "No", 8, 6, "", 2, "No", "", 1]
  • Вопрос задан
  • 559 просмотров
Подписаться 2 Средний 2 комментария
Решения вопроса 2
sergiks
@sergiks Куратор тега JavaScript
♬♬
const numSort = (arr) => arr.reduce(
  (acc, c, i) => {
    if (Number.isFinite(c)) arr.splice(i, 1, acc.shift());
    return acc.length ? acc : arr;
  },
  arr.filter((el) => Number.isFinite(el)).sort((a, b) => b - a)
);

numSort([2, "No", 6, 8, "", 1, "No", "", 10])
// [ 10, "No", 8, 6, "", 2, "No", "", 1 ]
как работает

arr.filter((el) => Number.isFinite(el)).sort((a, b) => b - a)
эта строка отбирает из массива только числа и сортирует их по убыванию. Получившийся сортированный массив чисел используется в reduce() как аккумулятор.

reduce() проходит по всем элементам исходного массива. Если встретилось число (не важно, какое), его заменяет на очередное (по убыванию) из полученного выше сортированного массива. Наконец, если массив с числами опустел – возвращается полностью обработанный массив.

После замены последнего числа возвращается основной массив. И прокручиваются оставшиеся не-числа. С ними условие не срабатывает и больше замен не происходит.

Фиддл


upd. в реале ТС требовалось работать с массивом объектов. Тогда так:
{
const arr = [{ACCOUNT: 2, PAY: "bla"},
{ACCOUNT: "No", PAY: "bla"},
{ACCOUNT: 6, PAY: "bla"},
{ACCOUNT: 8, PAY: "bla"},
{ACCOUNT: "", PAY: "bla"},
{ACCOUNT: 1, PAY: "bla"},
{ACCOUNT: "No", PAY: "bla"},
{ACCOUNT: "", PAY: "bla"},
{ACCOUNT: 10, PAY: "bla"}];


const nums = arr.filter((el) => Number.isFinite(el.ACCOUNT)).sort((a, b) => b.ACCOUNT - a.ACCOUNT);
const result = arr.map((el) => Number.isFinite(el.ACCOUNT) ? nums.shift() : el);

console.log(result);
}
Ответ написан
Taraflex
@Taraflex
Ищу работу. Контакты в профиле.
const a =  [2, 'No', 6, 8, '', 1, 'No', '', 10];
const nums = a.filter(Number.isFinite).sort((x,y)=>x-y);

console.log(a.map(v => Number.isFinite(v) ? nums.pop() : v));
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
WblCHA
@WblCHA
Думал-думал, и придумал более элегантное (или наркоманское) решение.)))
const testArr = [2, "No", 6, 8, "", 1, "No", "", 10];

const sortNumbers = (arr, sortFn = (a, b) => a - b) => {
  const numbers = [];
  arr.forEach((value, i, target) => {
    if (typeof value === 'number') {
      Object.defineProperty(numbers, numbers.length, {
        get: () => target[i],
        set: (v) => target[i] = v,
      });
    }
  });

  numbers.sort(sortFn);

  return arr;
}

console.log(sortNumbers(testArr, (a, b) => b - a)); // [ 10, "No", 8, 6, "", 2, "No", "", 1 ]


Old
const testArr = [2, "No", 6, 8, "", 1, "No", "", 10];

const sortNumbers = (arr, sortFn = (a, b) => a - b) => {
  const numbers = {
    pushByIndex(i) {
      Object.defineProperty(this, this.length, {
        get: () => arr[i],
        set: (value) => arr[i] = value,
      });
      this.length++;
    },
    length: 0,
  };

  arr.forEach((value, i) => {
    if(typeof value === 'number') {
      numbers.pushByIndex(i);
    }
  });

  Array.prototype.sort.call(numbers, sortFn);

  return arr;
}

sortNumbers(testArr, (a, b) => b - a); // [ 10, "No", 8, 6, "", 2, "No", "", 1 ]

Сергей Соколов, зацени.)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы