skip to Main Content
const test = [{a:1},{b:2},{c:3},{d:4},{a:5},{b:6},{c:7},{a:8},{c:9}]

Need output like below,
On repeat of key "a", need to create new array till the same key repeat

[{a:1},{b:2},{c:3},{d:4}]
[{a:5},{b:6},{c:7}]
[{a:8},{c:9}]

4

Answers


  1. You can try some thing like below.

    const test = [
      { a: 1 },
      { b: 2 },
      { c: 3 },
      { d: 4 },
      { a: 5 },
      { b: 6 },
      { c: 7 },
      { a: 8 },
      { c: 9 },
    ];
    
    const splitByRepeat = (arr) => {
      const result = [];
      let row = [];
      arr.forEach((item) => {
        const key = Object.keys(item)[0];
        if (key === "a") {
          if (row.length > 0) {
            result.push(row);
          }
          row = [item];
        } else {
          row.push(item);
        }
      });
      if (row.length > 0) {
        result.push(row);
      }
      return result;
    };
    
    console.log(splitByRepeat(test));
    Login or Signup to reply.
  2. You can achieve this with reduce function.

    const test = [{a:1},{b:2},{c:3},{d:4},{a:5},{b:6},{c:7},{a:8},{c:9}];
    
    const output = test.reduce((result, item) => {
        if ('a' in item) {
            result.push([]);
        }
        result[result.length - 1].push(item);
        return result;
    }, [[]]).filter(arr => arr.length > 0);
    

    Here, reduce function is used to iterate through the test array and accumulate elements into subarrays. Whenever an object with the key "a" is encountered, a new empty subarray is added to the result. Elements are then pushed into the most recent subarray.

    Finally, the resulting subarrays are filtered to remove any empty ones, and the output will contain the desired grouped arrays.

    Login or Signup to reply.
  3. Example using Array.prototype.reduceRight(), Array.prototype.unshift() and Array.prototype.splice()

    const test = [{a:1},{b:2},{c:3},{d:4},{a:5},{b:6},{c:7},{a:8},{c:9}];
    
    const result = [...test].reduceRight((acc, ob, i, ref) => 
      (ob["a"] && acc.unshift(ref.splice(i)), acc)
    , []);
    
    console.log(result);

    the test array if first shallow cloned using the Array Spread syntax [...test] and later referenced as ref. On every reduceRight iteration, if the ob["a"] && matches we append to the accumulator Array acc the contents of the ref clone from index i to the end. Splice modifies the ref array making it smaller and smaller. So basically what it does is: takes from ref chunks of array data and inserts them into acc – returning it.

    And there you have the 2D (nested) result Array:

    result.forEach(chunk => console.log(chunk));
    // [{a:1},{b:2},{c:3},{d:4}]
    // [{a:5},{b:6},{c:7}]
    // [{a:8},{c:9}]
    
    Login or Signup to reply.
  4. For the best performance don’t mutate the source and don’t push by 1 element, rather slice:

    const test = [{a:1},{b:2},{c:3},{d:4},{a:5},{b:6},{c:7},{a:8},{c:9}];
    
    let result = [], prev = 0, i = 0, [sc] = Object.keys(test[0]);
    while(++i < test.length) test[i][sc] && result.push(test.slice(prev, prev = i));
    result.push(test.slice(prev));
    
    result.forEach(item => console.log(JSON.stringify(item)));

    And a benchmark:

    enter image description here

    <script benchmark data-count="5000000">
    const test = [{a:1},{b:2},{c:3},{d:4},{a:5},{b:6},{c:7},{a:8},{c:9}];
    
    // @benchmark Roko C. Buljan
    [...test].reduceRight((acc, ob, i, ref) => 
      (ob["a"] && acc.unshift(ref.splice(i)), acc)
    , []);
    
    // @benchmark Siva KV
    {
    const result = [];
    let row = [];
    test.forEach((item) => {
      const key = Object.keys(item)[0];
      if (key === "a") {
        if (row.length > 0) {
          result.push(row);
        }
        row = [item];
      } else {
        row.push(item);
      }
    });
    if (row.length > 0) {
      result.push(row);
    }
    result;
    }
    
    // @benchmark Alexander
    let result = [], prev = 0, i = 0, [sc] = Object.keys(test[0]);
    while(++i < test.length) test[i][sc] && result.push(test.slice(prev, prev = i));
    result.push(test.slice(prev));
    result;
    </script>
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search