2

i have a array with objects in it. I need to create multiple arrays with objects grouped by one of the properties value. To clarify here is my array:

var people = [
    new Person("Scott", "Guthrie", 38),
    new Person("Scott", "Johns", 36),
    new Person("Scott", "Hanselman", 39),
    new Person("Jesse", "Liberty", 57),
    new Person("Jon", "Skeet", 38)
];

I want to have one array with all the people with first name Scott, one with all with the first name Jesse and so on. Any suggestions will be helpful.

1

2 Answers 2

4

To do that, you can loop through the array entries (in any of several ways, let's use forEach here) and create an object or Map keyed by the names you come across, with the value being the arrays of entries for those names.

Here's an example using an object:

// Create an object with no prototype, so it doesn't have "toString"
// or "valueOf", although those would be unlikely names for people to have
var nameArrays = Object.create(null);

// Loop the people array
people.forEach(function(person) {
    // Get the name array for this person's name, if any
    var nameArray = nameArrays[person.firstName];
    if (!nameArray) {
        // There wasn't one, create it
        nameArray = nameArrays[person.firstName] = [];
    }
    // Add this entry
    nameArray.push(person);
});

Live Example:

function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}
var people = [
  new Person("Scott", "Guthrie", 38),
  new Person("Scott", "Johns", 36),
  new Person("Scott", "Hanselman", 39),
  new Person("Jesse", "Liberty", 57),
  new Person("Jon", "Skeet", 38)
];

// Create an object with no prototype, so it doesn't have "toString"
// or "valueOf", although those would be unlikely names for people to have
var nameArrays = Object.create(null);

// Loop the people array
people.forEach(function(person) {
  // Get the name array for this person's name, if any
  var nameArray = nameArrays[person.firstName];
  if (!nameArray) {
    // There wasn't one, create it
    nameArray = nameArrays[person.firstName] = [];
  }
  // Add this entry
  nameArray.push(person);
});

// Show results
Object.keys(nameArrays).sort().forEach(function(firstName) {
  snippet.log(
    "People named " + firstName +
    ": " +
    nameArrays[firstName].map(function(person) {
      return person.firstName + " " + person.lastName;
    }).join(", ")
  );
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


ES2015 adds Maps to the language, so in an ES2015 environment we might use a Map rather than an object for our nameArrays:

// Creating the map:
let nameArrays = new Map();

// Getting an array:
nameArray = nameArrays.get(person.firstName);

// Adding an array:
nameArrays.set(person.firstName, []);

// Looping through the map:
for (let [firstName, nameArray] of nameArrays) {
    // Use `firstName` and `nameArray` here
}
Sign up to request clarification or add additional context in comments.

2 Comments

why do you sort (on firstname), when the firstnames are always the same?
@NinaScholz: I don't, I sort the property names from the object containing the name arrays so I output those arrays in order by the name.
2

This is a more generic solution. getGroupedBy(persons, key) returns an array of arrays with the grouped persons by the key.

function Person(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}

var people = [
    new Person("Scott", "Guthrie", 38),
    new Person("Scott", "Johns", 36),
    new Person("Scott", "Hanselman", 39),
    new Person("Jesse", "Liberty", 57),
    new Person("Jon", "Skeet", 38)
];

function getGroupedBy(persons, key) {
    var groups = {}, result = [];
    persons.forEach(function (a) {
        if (!(a[key] in groups)) {
            groups[a[key]] = [];
            result.push(groups[a[key]]);
        }
        groups[a[key]].push(a);
    });
    return result;
}

document.write('<pre>' + JSON.stringify(getGroupedBy(people, 'firstName'), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(getGroupedBy(people, 'lastName'), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(getGroupedBy(people, 'age'), 0, 4) + '</pre>');

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.