Tips on dividing or forming an array based on a duplicate key that repeats multiple times

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

To achieve the desired output where a new array is created on repeat of key "a," follow the format below:

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

Answer №1

For optimal performance, it is recommended not to modify the original source and avoid adding elements one by one. Instead, use the slice method:

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) sc in test[i] && result.push(test.slice(prev, prev = i));
result.push(test.slice(prev));

result.forEach(item => console.log(JSON.stringify(item)));

Here is a benchmark comparison:

` Chrome/125
-------------------------------------------------------
Alexander       ■ 1.00x | x10000000 570 579 608 626 627
Siva KV           1.93x |  x1000000 110 114 120 128 134
Roko C. Buljan    2.77x |  x1000000 158 159 166 169 170
------------------------------------------------------- `

Open in the playground

<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.hasOwnProperty("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])[0];
while(++i < test.length) sc in test[i] && 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>

Answer №2

If you're looking to experiment a bit, here's an example you can try out:

const sampleData = [
  { apple: 1 },
  { banana: 2 },
  { cherry: 3 },
  { date: 4 },
  { apple: 5 },
  { banana: 6 },
  { cherry: 7 },
  { apple: 8 },
  { cherry: 9 },
];

const organizeByFirstKey = (arr) => {
  const result = [];
  let row = [];
  arr.forEach((item) => {
    const key = Object.keys(item)[0];
    if (key === "apple") {
      if (row.length > 0) {
        result.push(row);
      }
      row = [item];
    } else {
      row.push(item);
    }
  });
  if (row.length > 0) {
    result.push(row);
  }
  return result;
};

console.log(organizeByFirstKey(sampleData));

Answer №3

It is important to keep track of the slice position index labeled as x. Slice the array starting from index x up to index i, and push those chunks into an Array named result:

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

const result = [], length = test.length - 1;
let x = 0, i = 0;
while (i<=length) (i++ === length || Object.hasOwn(test[i], "a")) && result.push(test.slice(x, x=i));

console.log(result);

Do note that Object.hasOwn() serves as a replacement for Object.prototype.hasOwnProperty(). It is advised to use Object.hasOwn() over the in operator. Using the in operator may offer a speed boost of 33%, but it can potentially yield incorrect results by returning true for inherited properties.


Alternatively, a slower example (~55% slower in performance) involves a backward approach utilizing 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((accumulator, obj, index, reference) =>
  (Object.hasOwn(obj, "a") && accumulator.unshift(reference.splice(index)), accumulator)
, []);

console.log(result);

The test array is initially shallow cloned using the Array Spread syntax [...test] and referenced as reference. During each reduceRight iteration, if

obj.hasOwnProperty("a") &&
condition matches, we add to the accumulator Array accumulator the contents of the reference clone from index index to the end. The splice operation modifies the reference array gradually reducing its size. Essentially, this process involves retrieving chunks of array data from reference and incorporating them into accumulator, which is then returned.

Answer №4

To accomplish this task, one can utilize the reduce function.

const data = [{x:1},{y:2},{z:3},{w:4},{x:5},{y:6},{z:7},{x:8},{z:9}];

const result = data.reduce((accumulated, item) => {
    if ('x' in item) {
        accumulated.push([]);
    }
    accumulated[accumulated.length - 1].push(item);
    return accumulated;
}, [[]]).filter(subarray => subarray.length > 0);

In this code snippet, the reduce function is employed to loop through the data array and group elements into subarrays. Whenever an object with the key "x" is found, a new empty subarray is appended to the result. Subsequently, items are inserted into the most recent subarray.

Ultimately, the generated subarrays are filtered to eliminate any empty ones, yielding the desired grouped arrays in the output.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Prevent external scrolling while Bootstrap modal is active

<div class="modal mt-5p" role="dialog" [ngStyle]="{'display':IONotes}"> <div class="modal-dialog modal-md mt-0px width-70p"> <div class="modal-content" style="height:500 ...

Encountering issues when dynamically altering the material texture in three.js during runtime

Having full control over a material, changing its color at runtime is seamless. However, attempting to change the map texture results in an error. For instance: var materials = mesh.material.materials; materials[index].color.setHex(0xb60430); materials[i ...

Can someone advise me on how to ensure my function effectively delivers a desired outcome?

My goal is to learn Javascript on my own, but I'm struggling to make progress. I've created a function called fixedSpending() that takes two inputs, num1 and num2, and adds them together. However, when the user hits the "=" button, I expect the f ...

Identify the CSS class for the ionic component on the webpage

Currently, I am in the process of developing an application using ionic 2 and angular 2. Within this app, I am utilizing the ionic 2 component known as ModalController. Unfortunately, I have encountered a challenge when attempting to adjust the size of th ...

Locate a group of DOM selectors that correspond to the highlighted text

Imagine you're at a certain location and you highlight some text: https://i.sstatic.net/8PGvD.png When you inspect the DOM, you see it's represented like this: https://i.sstatic.net/rL0Og.png The actual text is: "Local embassy – For Wikiped ...

Transfer a variable from javascript/jquery to a PHP script within the same page

Possible Duplicate: How to transfer JavaScript variables to PHP without using a form? What is the best way to move a JavaScript variable to a PHP script without the need for form submission? Is this even achievable? Ajax seems to be a viable solutio ...

Explore our array of images displayed in an interactive gallery featuring clickable

I have a query I'm facing an issue with my code. Currently, I have a gallery that displays images perfectly. Now, I want to enhance it by showing a larger resolution of the image when clicked. However, when I add the href tag to link the images, they ...

Disable the resizing and responsiveness features in the jQuery Basic Slider

I'm currently utilizing the Basic jQuery Slider from the Basic Slider website, and I am attempting to eliminate the responsive/resize feature. My goal is to keep the slider contained within a centered div without changing its size. However, whenever I ...

What is the solution to preventing Angular 1.3 ngMessages from affecting the size of my form?

Hey there, I'm diving into front-end design for the first time. My issue is with a form that I want to use ng-messages for validation error messages. Currently, my form's size changes depending on whether there are errors displayed or not, and it ...

Having trouble getting the CSS animation to work properly with the text

Update: The direct link is working fine, unlike the rocketscript version. <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> I have been attempting to animate word rotati ...

Issue with Jenkins running Cucumber causing timeout on JavaScript form

My current setup involves Cucumber 1.2.1 with Watir-webdriver 0.6.1 for webpage testing. While the tests run smoothly on my local machine, I encounter a timeout issue on a CI machine (Jenkins) when trying to fill out a javascript form. Despite having emai ...

Exploring the Dynamic Connection: AngularJS and MongoDB

As someone who is new to MEAN stack, I am currently working on creating a simple one-page application. My goal is to connect to MongoDB and retrieve values from a specific collection using a controller. During my search for an answer, I stumbled upon this ...

Sorting swiftly using pointers

For my homework assignment, I am tasked with coding a quick sort algorithm in C. The given prototype is as follows: static inline int* choose_pivot(int *left, int *right) { /* FIX ME */ } /* * partition(left, right, pivot): push value less than *piv ...

setInterval versus delay

I am attempting to create a div that bounces every 4 seconds, then fades out after 15 seconds. However, the current code isn't working as expected - the div disappears and the bounce effect doesn't occur. $(document).ready(function(){ functi ...

Choose all elements with a specific class name without the need to specify their position in the list

I'm working on adding a function to my WordPress site that will allow me to show/hide page elements with a specific class. For example, I want any elements (such as rows, containers, and text blocks) that have the 'show-hide' class to be hid ...

Is it wrong to use <match v-for='match in matches' v-bind:match='match'></match>? Am I allowed to incorporate the match variable from the v-for loop into the v-bind attribute on the

I am attempting to display HTML for each individual match within the matches array. However, I am uncertain if <match v-for='match in matches' v-bind:match='match'></match> is the correct syntax to achieve this. To clarify, ...

Different ways to activate the system bell in Node.js

Currently, I have a custom nodejs script running for an extended period and I'm seeking a way to receive a notification once the script finishes its execution. Is there a method in nodejs that can be used to activate the "System Bell" alert? ...

Could implementing a click/keydown listener on each cell in a large React datagrid with thousands of cells impact performance?

Years ago, before the advent of React, I mastered linking events to tables by attaching the listener to the <tbody> and extracting the true source of the event from the event target. This method allowed for a single listener for the entire table, as ...

Eliminate the prefixes of object keys in Node.js

This is my first time reaching out for help on a forum. I've been struggling with an issue for days and haven't been able to find a solution. It all started with a database query that returned the following data: { "prod_format": "400 ml", "pro ...

Is there a way to modify the color of my question post-submission?

Within my code, there are numerous queries that need to be addressed. Upon submission, I desire to alter the color of each question to green if the response is correct, or red if it is incorrect. document.getElementById("submit-button").addEventLi ...