JS:按两个不同的属性对JSON数组进行排序,并保持在数组中指定的顺序

时间:2019-09-12 04:11:16

标签: javascript

我有一个需要排序的JSON对象数组。该数组需要按两个不同的属性进行排序。首先,应使用found属性按字母顺序对数组进行排序。其次,应该对数组进行排序,以使website属性以siteOrder中指定的相同顺序降序。

var siteOrder = ['facebook', 'twitter', 'reddit', 'youtube', 'instagram'];
var data = [
    {found: 'booker', website: 'reddit'},
    {found: 'john', website: 'facebook'},
    {found: 'walter', website: 'twitter'},
    {found: 'smith', website: 'instagram'},
    {found: 'steve', website: 'youtube'},
    {found: 'smith', website: 'facebook'},
    {found: 'steve', website: 'twitter'},
    {found: 'john', website: 'instagram'},
    {found: 'walter', website: 'youtube'}
];

/* Example output: Sorted output by found, respecting the order of the websites specified
{found: 'booker', website: 'reddit'},
{found: 'john', website: 'facebook'},
{found: 'john', website: 'instagram'},
{found: 'smith', website: 'facebook'},
{found: 'smith', website: 'instagram'},
{found: 'steve', website: 'twitter'},
{found: 'steve', website: 'youtube'},
{found: 'walter', website: 'twitter'},
{found: 'walter', website: 'youtube'}
*/

我可以使用以下找到的属性按字母顺序对它们进行排序:

data.sort(function(a, b) {
    var textA = a.found.toUpperCase();
    var textB = b.found.toUpperCase();
    return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});

但是我不知道如何使其也遵守网站的指定顺序。

4 个答案:

答案 0 :(得分:2)

如果找到的两个对象的文本相同,则比较siteOrder中两个对象的网站索引。

data.sort(function (a, b) {
  var textA = a.found.toUpperCase();
  var textB = b.found.toUpperCase();
  var foundOrder = (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
  if (foundOrder === 0) {
    var indexA = siteOrder.indexOf(a.website);
    var indexB = siteOrder.indexOf(b.website);
    return (indexA < indexB) ? -1 : (indexA > indexB) ? 1 : 0;
  }
  return foundOrder;
});

答案 1 :(得分:0)

var siteOrder = ['facebook', 'twitter', 'reddit', 'youtube', 'instagram'];
var data = [
    {found: 'booker', website: 'reddit'},
    {found: 'john', website: 'facebook'},
    {found: 'walter', website: 'twitter'},
    {found: 'smith', website: 'instagram'},
    {found: 'steve', website: 'youtube'},
    {found: 'smith', website: 'facebook'},
    {found: 'steve', website: 'twitter'},
    {found: 'john', website: 'instagram'},
    {found: 'walter', website: 'youtube'}
];

// For performance, add a property that is the index of the website in the list
data.forEach(o => o.siteIndex = siteOrder.indexOf(o.website));

// If the `found` of each object is the same, then use the index of the
// website as the sort criteria, otherwise compare the `found` props
data.sort((a, b) =>
  a.found === b.found ? a.siteIndex - b.siteIndex : a.found.localeCompare(b.found)
);

// Remove the optimization property
data.forEach(o => delete o.siteIndex);

console.log(data);

答案 2 :(得分:0)

var siteOrder = ["facebook", "twitter", "reddit", "youtube", "instagram"];
var data = [{
    found: "booker",
    website: "reddit"
  },
  {
    found: "john",
    website: "facebook"
  },
  {
    found: "walter",
    website: "twitter"
  },
  {
    found: "smith",
    website: "instagram"
  },
  {
    found: "steve",
    website: "youtube"
  },
  {
    found: "smith",
    website: "facebook"
  },
  {
    found: "steve",
    website: "twitter"
  },
  {
    found: "john",
    website: "instagram"
  },
  {
    found: "walter",
    website: "youtube"
  }
];

const result = data.sort((a, b) => {
  const textA = a.found.toUpperCase();
  const textB = b.found.toUpperCase();

  if (textA < textB) {
    return -1;
  } else if (textA > textB) {
    return 1;
  }

  const siteA = siteOrder.indexOf(a.website);
  const siteB = siteOrder.indexOf(b.website);

  if (siteA < siteB) {
    return -1;
  } else if (siteA > siteB) {
    return 1;
  } else {
    return 0;
  }
});

console.log(result);

答案 3 :(得分:0)

这可以通过指定一个排序处理程序来实现;

  • 首先根据found字段比较一对项目。如果项目不匹配,请分别返回-11
  • 如果每个当前项目的found字段均匹配,则根据相同的方式(返回-110)对这些项目对进行排序website数组中每个项目的sortOrder字段的索引上

可以实现如下所示:

var siteOrder = ['facebook', 'twitter', 'reddit', 'youtube', 'instagram'];
var data = [
    {found: 'booker', website: 'reddit'},
    {found: 'john', website: 'facebook'},
    {found: 'walter', website: 'twitter'},
    {found: 'smith', website: 'instagram'},
    {found: 'steve', website: 'youtube'},
    {found: 'smith', website: 'facebook'},
    {found: 'steve', website: 'twitter'},
    {found: 'john', website: 'instagram'},
    {found: 'walter', website: 'youtube'}
];

data.sort((itemA, itemB) => {
  
  const foundA = itemA.found.toLowerCase();
  const foundB = itemB.found.toLowerCase();
  
  /* Sort based on found (primary criteria) */
  if(foundA < foundB) return -1;
  if(foundA > foundB) return 1;
  
  /* If foundA and foundB are equivilant, sort 
  based on website (secondary criteria) */
  const websiteA = itemA.website.toLowerCase();
  const websiteB = itemB.website.toLowerCase();
  
  /* Find index of each site, relative to the siteOrder array */
  const siteA = siteOrder.indexOf(websiteA);
  const siteB = siteOrder.indexOf(websiteB);
  
  /* Sort items that have matching found values, by the index that site
  values occour in the siteOrder */
  website values in
  if(siteA < siteB) return -1;
  if(siteA > siteB) return 1;
  
  return 0;
});

console.log(data);