Сортировка массива значений объектов в алфавитном порядке c, а затем в порядке чисел c - PullRequest
0 голосов
/ 20 января 2020

У меня есть массив объектов примерно так:

[
  {key: "key1", label: "1"},
  {key: "key2", label: "3"},
  {key: "key3", label: "2"}, 
  {key: "key4", label: "Second"}, 
  {key: "key5", label: "First"}
] 

Я бы хотел отсортировать этот массив так, чтобы алфавитные значения были первыми, вот так:

[
  {key: "key5", label: "First"},
  {key: "key4", label: "Second"}, 
  {key: "key1", label: "1"},
  {key: "key3", label: "2"}, 
  {key: "key2", label: "3"}    
] 

Я придумал это решение:

sortArray(list: any[], key: string) {
  return list.sort(compare);

  function compare(a, b) {
    const aIsAlphabetic = isAlphabetical(a[key]);
    const bIsAlphabetic = isAlphabetical(b[key]);

    if (aIsAlphabetic && !bIsAlphabetic) {
      return -1;
    } else if (bIsAlphabetic && !aIsAlphabetic) {
      return 1;
    }

    if (a[key] < b[key]) {
      return -1;
    }
    if (a[key] > b[key]) {
      return 1;
    }
    return 0;
  }

  function isAlphabetical(value: string) {
    return value.match(/[a-zA-Z]/i);
  }
}

Решение работает, но мне не нравится идея объявления нескольких функций внутри sortArray, я делаю это правильно? Или есть еще какие-нибудь советы, чтобы сделать правильно?

Ответы [ 3 ]

1 голос
/ 20 января 2020

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

const sortArray = (arr, key, rgx, bothMatched, neitherMatched, onlyAMatched, onlyBMatched) => {
  const compare = (a, b) => {   
    const aval = a[key] || "";
    const bval = b[key] || "";
    const amatched = aval.match(rgx);
    const bmatched = bval.match(rgx);   
    if (amatched) {
      if (bmatched) {     
        return bothMatched(aval,bval);
      }    
      return onlyAMatched(a,b);
    }
    if (bmatched) {   
      return onlyBMatched(a,b)
    }     
    return neitherMatched(aval,bval);
  };  

  return arr.sort(compare);
};
 
const arr = [
  {key: "key1", label: "1"},
  {key: "key2", label: "3"},
  {key: "key3", label: "2"}, 
  {key: "key4", label: "Second"}, 
  {key: "key5", label: "First"}
] 
const key = 'label';

console.log("----- match like OP -----");
sortArray(
  arr, 
  key, 
  /[a-zA-Z]/i,
  (a,b) => a.localeCompare(b),
  (a,b) => a.localeCompare(b), 
  () => -1,
  () => 1)
.forEach(e => console.log(JSON.stringify(e)));

console.log("----- Alternative match -----");
sortArray(
  arr, 
  key, 
  /^[\d]+$/,
  (a,b) => parseInt(a,10) - parseInt(b,10), 
  (a,b) => a.localeCompare(b),
  () => 1,
  () => -1)
.forEach(e => console.log(JSON.stringify(e)));
console.log(".");
1 голос
/ 21 января 2020

Этого должно быть достаточно. Шаблон «a-zA-Z» не является безопасным для других языков.

let array=[{key: "key1", label: "1"}, {key: "key2", label: "3"}, {key: "key3", label: "2"}, {key: "key4", label: "Second"},{key: "key5", label: "First"}]
let isAlphanumeric = (value:string) => (value.match(/[a-zA-Z]/i))

console.log(array.sort((a, b) => a.label.localeCompare(b.label))
.filter(obj => isAlphanumeric(obj.label))
.concat(array.filter(obj => !isAlphanumeric(obj.label))))
1 голос
/ 20 января 2020

Это вопрос, основанный на мнении, особенно с участием javascript / typcript!

Короткий ответ: правильного ответа нет. Ваш код, как вы сказали, работает! Он также чистый, читабельный и лаконичный.

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

Лично я бы просто переместил эти вложенные функции в высокий Уровень уровня, чтобы я мог проверить их по отдельности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...