1

Sorry about the title, I'm really not sure how to word this. I'm stuck, I need to sort an array by its object's title property value, into the same order of a second array of strings.

Basically, I have two arrays...

var titles = [
  'title1',
  'title2',
  'title3',
  'title4',
  'title5'
]

var objects = [
  {
    title: 'title5',
    ...//other values
  }, {
    title: 'title3',
    ...//other values
  }
  , {
    title: 'title4',
    ...//other values
  }, {
    title: 'title1',
    ...//other values
  }, {
    title: 'title2',
    ...//other values
  } 
]

I want to order the objects array in the same order as the strings in titles array. Is this possible? My code base has access to _underscore, or I can use plain ES6.

3
  • you want to sort() them on base of their last number? Commented Feb 11, 2019 at 11:26
  • no, whatever the order of the titles array is, those values could be anything as they are strings. Commented Feb 11, 2019 at 11:30
  • think of the titles array as a configuration for displaying the objects array. We use this currently to filter the objects array to contain only the match values, but i also now need to sort it in the same order. Commented Feb 11, 2019 at 11:34

5 Answers 5

2

You could create object from titles array and use it for ordering your array of objects.

var objects = [{"title":"title5"},{"title":"title3"},{"title":"title4"},{"title":"title1"},{"title":"title2"}]
var titles = ['title1','title2','title3','title4','title5'].reduce((r, e, i) => Object.assign(r, {[e]: i}), {})

objects.sort((a, b) => titles[a.title] - titles[b.title])
console.log(objects)

Sign up to request clarification or add additional context in comments.

3 Comments

This works only because you assume titles are in alphabetical order.
That's not true @UlysseBN -- it's sorting by the index in the array as it should. This is a good, efficient way to do this.
Oh I didn't see the index, maybe you should use more readable variables :)
1

Yes, it's very possible. I personally would follow the 'decorate-sort-undecorate' pattern:

var titles = [
  'title1',
  'title2',
  'title3',
  'title4',
  'title5'
]

var objects = [
  {
    title: 'title5',
    //other values
  }, {
    title: 'title3',
    //other values
  }
  , {
    title: 'title4',
    //other values
  }, {
    title: 'title1',
    //other values
  }, {
    title: 'title2',
    //other values
  } 
]

var rankings = objects.map( o => ({
    object: o,
    ranking: titles.indexOf(o.title)
}))

rankings.sort((a, b) => a.ranking-b.ranking)

var sortedObjects = rankings.map(r => r.object);

console.log(sortedObjects);

Comments

0

You could use _.indexBy to create an Object from objects variable and then map titles:

const objectsByTitle = _.indexBy(objects, 'title');
const result = titles.map(it => objectsByTitle[it]);

Titles should be unique ofc.

Comments

-1

Can you check if this resolve what you are needing for?

var titles = [
  'title1',
  'title2',
  'title3',
  'title4',
  'title5'
]

var objects = [
  {
    title: 'title5',
  }, {
    title: 'title3',
  }
  , {
    title: 'title4',
  }, {
    title: 'title1',
  }, {
    title: 'title2',
  } 
]

function compare(a,b) {
  if (a.title < b.title)
    return -1;
  if (a.title > b.title)
    return 1;
  return 0;
}

console.log(objects.sort(compare));

https://jsfiddle.net/sxtn57gj/

1 Comment

The op doesn't want to sort by title, they want to sort by where the title apprears in titles array, which you are ignoring.
-1

There is a simple (but costful) solution:

let titles = ['foo', 'bar', 'fizz', 'buzz']

let objects = [{title: 'fizz'}, {title: 'bar'}, {title: 'buzz'}, {title: 'foo'}]

console.log(titles.map(title => objects.find(o => o.title === title)))

However this is a o(n²) solution, I'm pretty sure your needs may be a little bit different and you could user an object, with title as keys.

2 Comments

I didn't downvote this — it works and might be good enough, but I suspect the downvote is because this is a quadratic time solution when a O(nlogn) solution exists.
@MarkMeyer I'd love to agree, but I wrote it in my answer already... I'll precise though, thanks for the comment.

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.