Сортировка массива, содержащего объекты, с использованием сложных / динамических c критериев (по возрастанию и по убыванию)? - PullRequest
1 голос
/ 07 мая 2020

У нас есть массив с данными, и я хочу отсортировать его по ключу users:

  • Если users имеет 1 объект, я сортирую его по свойству name.

  • Если users имеет более одной записи, я сортирую по users.length.

Пример:

DESCENDING: Zorya, Gorya, Dorya, Borya, Aorya, 4, 2, 0

 ASCENDING: Aorya, Borya, Dorya, Gorya, Zorya, 2, 4, 0

Вот что я сделал до сих пор:

const array = [{
  name: "qw",
  users: [
    { name: "Borya" },
  ],
}, {
  name: "qw",
  users: [
    { name: "Gorya" },
  ],
}, {
  name: "qw",
  users: [
   { name: "Zorya" },
 ]
}, {
  name: "qw",
  users: [
    { name: "Var" },
    { name: "Var2" },
  ],
}, {
  name: "qw",
  users: [],
}, {
  name: "qw",
  users: [
    { name: "Aorya" },
  ],
}, {
  name: "qw",
  users: [
    { name: "rwerwerwe" },
    { name: "tregdf" },
    { name: "gdfgdf" },
    { name: "Vayetrtertrr2" },
  ]
}, {
  name: "qw",
  users: [
   { name: "Dorya" },
  ],
}];

function orderCustomBy(collection, key, direction) {
  const direct = direction === "desc" ? -1 : 1;
  
  let compare = (a, b) => {
    if (a === null) return -1;
    if (b === null) return 1;
    // Just commenting this out because there's no `intlCollator` in here:
    // return intlCollator.compare(a, b);
  };
  
  if (key === "users") {
    compare = (a, b) => {
      // What should go in here?
      // intlCollator.compare(a[0].name, b[0].name);
      
      return 1;
    };
  }
  
  return [].concat(collection).sort((a, b) => {
    const result = compare(a[key], b[key]);
    return result * direct;
  });
}

console.log(orderCustomBy(array, 'users', 'asc')
  .map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
  
console.log(orderCustomBy(array, 'users', 'desc')
  .map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
  max-height: 100% !important;
}

Ответы [ 2 ]

1 голос
/ 07 мая 2020

В основном вам нужно учитывать несколько различных комбинаций внутри функции compare, когда key === 'users:

  • У обоих один пользователь, поэтому мы сравниваем user[0].name.

  • Только a имеет одного пользователя, поэтому a идет перед b.

  • Только b имеет одного пользователя , поэтому b идет перед a.

  • Ни у кого нет одного пользователя, поэтому мы просто сравниваем users.length.

Это будет выглядеть примерно так:

if (a.users.length === 1 && b.users.length === 1) {
  // If both have a single user, sort by users[0].name:
  return a.users[0].name.localeCompare(b.users[0].name);
} else if (a.users.length === 1) {
  // If only `a` has a single user, `a` goes before `b`:
  return -1;
} else if (b.users.length === 1) {
  // If only `b` has a single user, `b` goes before `a`:
  return 1;
}

// Otherwise, sort by users.length:
return a.users.length - b.users.length;

Здесь вы можете увидеть это в действии:

const array = [{
  name: "qw",
  users: [
    { name: "Borya" },
  ],
}, {
  name: "qw",
  users: [
    { name: "Gorya" },
  ],
}, {
  name: "qw",
  users: [
   { name: "Zorya" },
 ]
}, {
  name: "qw",
  users: [
    { name: "Var" },
    { name: "Var2" },
  ],
}, {
  name: "qw",
  users: [],
}, {
  name: "qw",
  users: [
    { name: "Aorya" },
  ],
}, {
  name: "qw",
  users: [
    { name: "rwerwerwe" },
    { name: "tregdf" },
    { name: "gdfgdf" },
    { name: "Vayetrtertrr2" },
  ]
}, {
  name: "qw",
  users: [
   { name: "Dorya" },
  ],
}];

function orderCustomBy(collection, key, direction) {
  const direct = direction === "desc" ? -1 : 1;
  
  let compare;
  
  if (key === "users") {
    compare = (a, b) => {
      if (a.users.length === 1 && b.users.length === 1) {
        // If both have a single user, sort by users[0].name:
        return a.users[0].name.localeCompare(b.users[0].name);
      } else if (a.users.length === 1) {
        // If only `a` has a single user, `a` goes before `b`:
        return -1;
      } else if (b.users.length === 1) {
        // If only `b` has a single user, `b` goes before `a`:
        return 1;
      }
      
      // Otherwise, sort by users.length:
      return a.users.length - b.users.length;
    };
  } else {
    compare = (a, b) => {
      if (a === null) return -1;
      if (b === null) return 1;
      // Just commenting this out because there's no `intlCollator` in here:
      // return intlCollator.compare(a, b);
    };
  }
  
  return [].concat(collection).sort((a, b) => compare(a, b) * direct);
}

console.log(orderCustomBy(array, 'users', 'asc')
  .map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
  
console.log(orderCustomBy(array, 'users', 'desc')
  .map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
  max-height: 100% !important;
}
0 голосов
/ 07 мая 2020

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

[ "Borya", "Gorya", "Zorya", "2", "0", "Aorya", "4", "Dorya" ]

Сортировка должна быть простой.

function simplifyArray (arr) {
  return arr.map(el => {
    let length = el.users.length;
    if (length === 1) { return el.users[0].name; }
    else return String(length);
  });
}

const array = [
{
    name: "qw",
    users: [
      { name: "Borya" }
    ]
  },
  {
    name: "qw",
    users: [
      { name: "Gorya" }
    ]
  },
  {
    name: "qw",
    users: [
     { name: "Zorya" }
   ]
  },
  {
    name: "qw",
    users: [
      { name: "Var" },
      { name: "Var2" }
    ]
  },
  {
    name: "qw",
    users: []
  },
  {
    name: "qw",
    users: [
      { name: "Aorya" }
    ]
  },
  {
    name: "qw",
    users: [
      { name: "rwerwerwe" },
      { name: "tregdf" },
      { name: "gdfgdf" },
      { name: "Vayetrtertrr2" }
    ]
  },
  {
    name: "qw",
    users: [
     { name: "Dorya" }
    ]
  },
];

const simplerArray = simplifyArray(array);

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