3
\$\begingroup\$

I'm transforming this:

[["Apples", "fruitgroup", "123"], ["Bananas", "fruitgroup", "012"], ["Jumbo Jet", "planegroup", "99"], ["Crop duster", "planegroup", "40"], ["Melons", "fruitgroup", "55"]]

into this:

["Apples or Bananas or Melons [x]", "Jumbo Jet or Crop duster [x]"]

Because basically I have to group the child arrays by whatever is in their second index, or [1], and then join them with " or ".

I am successful but I'm afraid this isn't really the best way to acheive this. Isn't there a more simple way to do this?

var 
  filters = [["Apples", "fruitgroup", "123"], ["Bananas", "fruitgroup", "012"], ["Jumbo Jet", "planegroup", "99"], ["Crop duster", "planegroup", "40"], ["Melons", "fruitgroup", "55"]],
  fieldnames = _.uniq(_.map(filters, function (filter) {
    return filter[1];
  })), 
  groups = _.groupBy(filters, function (filter) {
    return filter[1];
  }),
  strings = _.map(groups, function (group) {
    return _.map(group, function (item) {
      return item[0];
    }).join(" or ") + " [x]";
  });
console.log(strings);
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Honestly, this looks fine - as long as the other people using it are familiar with functional programming. It may not be particularly "elegant" (which to me is sometimes used as a synonym for 'clever') but I think that if your data are consistently formatted in this way then hardcoding the indexes is okay as long as it is documented. \$\endgroup\$ Commented Aug 26, 2015 at 17:39
  • \$\begingroup\$ Yes, the data I'm getting is consistently formatted this way. If they were to change the data we would probably get a deprecation notice for a few months... Without getting into too much detail, we are right now trying to see if we should either have the client modify the data like I have done here, or have the server do it. (It's an enterprise level app product, where there are lots of inter-services) So the server can either send the data as they are getting it, or they can modify it then send it to client, we haven't decided yet, but I wanted to ensure I'm providing a good POC clientside \$\endgroup\$
    – docodemore
    Commented Aug 26, 2015 at 18:21

1 Answer 1

3
\$\begingroup\$

The approach seems just fine to me.

However, I noticed that your fieldnames variable isn't actually used for anything. So that can go.

You can also use some shortcuts in underscore.js:

var groups, strings;

groups = _.groupBy(filters, 1); // group by index 1 (no need for a callback)

strings = _.map(groups, function (group) {
  return _.pluck(group, 0).join(" or ") + " [x]"; // pluck index 0 and join
});

As much as I like functional style, it does get a bit dense, so I've spread it out a tiny bit, rather than have it all as a run-on var declaration. (If it's an enterprise-level app, I imagine maintenance is a high-priority, so better to err on the side of clarity.)

You could also go the opposite way, and inline the _.groupBy, but I wouldn't recommend it. There's no performance gain, only readability pain.

A compromise might be undescore's chaining system:

var strings = _.chain(filters)
  .groupBy(1)
  .map(function (group) {
    return _.pluck(group, 0).join(" or ") + " [x]";  
  })
  .value();

But again, there's little need.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much! I like what you did with groupBy and with pluck. I'm going to adopt the first example, as I dont think it's necessary for a chain at this time. \$\endgroup\$
    – docodemore
    Commented Aug 27, 2015 at 17:14

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.