4

I have an array of JSON objects I need to sort. The array needs to be sorted by two different properties. First, the array should be alphabetically sorted by the found property. Second, the array should be sorted so that the website property descends in the same order specified in 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'}
*/

I can alphabetically sort the by the found property using:

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

However I do not know how to make it also respect the specified order of the websites.

1
  • 2
    You have an array of objects, not "JSON objects". Commented Sep 12, 2019 at 4:18

4 Answers 4

2

If the found text is same for 2 objects, then compare the index of the website of the 2 objects in 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;
});
Sign up to request clarification or add additional context in comments.

Comments

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);

Comments

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);

Comments

0

This can be achieved by specifying a sort handler that;

  • first compares a pair of items based on the found field. If the items are not a match, return -1 or 1 respectivly
  • if the found field of each of the current items do match, then sort those item pairs in the same way (returning -1, 1 or 0) based on the index of the website field of each item, in the sortOrder array

That can be implemented as shown below:

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.