1

Considering I'm having the array:

var arr = [
   {type:'a', name:'a1'}, {type:'b', name:'b1'}, {type:'hr'}, 
   {type:'a', name:'a2'}, {type:'b', name:'b2'}, {type:'hr'}, 
   {type:'a', name:'a3'}, {type:'b', name:'b2'}, {type:'hr'} 
]

I'd split it into array of arrays of objects using {type:'hr'} object as separator element. So the result is:

[
[{type:'a', name:'a1'}, {type:'b', name:'b1'}],
[{type:'a', name:'a3'}, {type:'b', name:'b2'}],
[{type:'a', name:'a3'}, {type:'b', name:'b3'}]
]

Think lodash is useful for it?

Currently I've used _.map for this:

 var result = [], sub = [];                                                                                                                                    _.map(tokens, (it, idx) => {                                                                                                                                      if(it.type === 'hr'){                                                     
        result.push(sub);                                                 
                sub = [];                                                 
            } else {                                                      
                sub.push(it);                                             
            }                                                             
        });                                                               
        if(sub.length){                                                   
            result.push(sub);                                             
        }                                                                 
    console.log(result);  
2
  • Let me see if I understand - you want a split that works similar to splitting a string, only with arrays. For example, with a string if you have "aaxbbxcc" and you split on x, you'll get ["aa", "bb", "cc"] whereas for your use case given an array like [ "a", "a", "x", "b", "b", "x", "c", "c"] and splitting on "x" should produce [ ["a", "a"], ["b", "b"], ["c", "c"] ]. Is that correct? Commented Sep 1, 2016 at 14:16
  • yep, you are correct Commented Sep 1, 2016 at 14:31

2 Answers 2

2

You could use reduce and create a new sub-array when you find {type:'hr'}:

var arr = [
   {type:'a', name:'a1'}, {type:'b', name:'b1'}, {type:'hr'}, 
   {type:'a', name:'a2'}, {type:'b', name:'b2'}, {type:'hr'}, 
   {type:'a', name:'a3'}, {type:'b', name:'b2'}, {type:'hr'} 
];
var delimiter = { type: 'hr' };
var res = _.reduce(arr, function(result, obj, index) {
  if (_.isEqual(obj, delimiter)) {
    if (index !== arr.length - 1) result.push([]);
  } else {
    _.last(result).push(obj);
  }
  return result;
}, [[]]);

console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

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

2 Comments

Yes, I believe this is the solution. I was about to post the same, but you were faster :P The only "problem" is that this will add an extra empty array, whereas OP's expected output doesn't have it. If indeed there shouldn't be empty arrays there, a simple filter will take care of that. However, that would be a separate thing operation - as far as I'm concerned, empty arrays in the results are correct - this is also how the string split operates adding empty strings if there is nothing to put in the delimiters.
@Vld Thanks. You're right. Added an extra condition to get rid of the last empty array.
1

Here's what I would do:

function splitBy(array, predicate, result = []) {
  const taken = _.takeWhile(array, predicate);
  const remaining = _.tail(_.dropWhile(array, predicate));

  return remaining.length ?
    splitBy(remaining, predicate, result.concat([taken])) :
    result.concat([taken]);
}

splitBy(
  arr,
  _.negate(_.partial(_.isEqual, { type: 'hr' })))
);

The idea is to use takeWhile() to get the items that don't match the separator. Then, dropWhile() creates the next chunk of array to iterate over by passing it to splitBy().

The actual predicate that's used to determine what the separator is is passed in as an argument, meaning that you can reuse this function for other kinds of separators.

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.