What is the best way to add items to arrays with matching titles?

I am currently working on a form that allows for the creation of duplicate sections. After submitting the form, it generates one large object. To better organize the data and make it compatible with my API, I am developing a filter function to group the duplicates into arrays.

For example:

// initial object


{
  question_10: ""
  question_10a: ""
  question_11_checkbox: false
  question_11_checkbox_copy_0: false
  question_11_checkbox_copy_1: true
  question_11_text: "110 Monroe St"
  question_11_text_copy_0: "186 Aspen Road"
  question_12_checkbox: false
  question_12_checkbox_copy_0: false
  question_12_text: "New York"
  question_12_text_copy_0: "South Orange"
  ...
}

// desired output


{
  question_10: ""
  question_10a: ""
  question_11_checkbox: false
  question_11_checkbox_copies: [
    { question_11_checkbox_copy_0: false } 
    { question_11_checkbox_copy_1: true }
  ]
  question_11_text: "101 Monroe St"
  question_11_text_copies: [
    { question_11_text_copy_0: "186 Aspen Road"}
  ]
  question_12_checkbox: false
  question_12_checkbox_copies: [
    { question_12_checkbox_copy_0: false}
  ]
  question_12_text: "New York"
  question_12_text_copies: [
    { question_12_text_copy_0: "South Orange"}
  ]

 ...
}

My progress so far involves filtering out the copies from the original object and creating arrays for them.


// filter out copy keys
const copiesKey = Object.keys(data).filter(key => key.includes('copy'));

const copy = {};

// create arrays for copies
copiesKey.map(copiedQuestion => {

  if (!(`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies` in copy)) {
    copy[`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies`] = [];
  }
});

However, I am facing difficulty in matching the objects to their respective arrays and pushing them.

For instance:


question_11_text_copies: [
  { question_11_text_copy_0: "186 Aspen Road" }
]

I have attempted to extract the last three keys of the copy_0 object and match it with the array name using array.filter, but it did not yield the expected results.

Can you provide guidance on how to correctly match the 'copy_n' objects to the corresponding array and push them?

Answer №1

Although it may seem a bit outdated, one effective solution is to utilize a for...in loop in conjunction with regex pattern matching against the key.

const data = {
  question_10: "",
  question_10a: "",
  question_11_checkbox: false,
  question_11_checkbox_copy_0: false,
  question_11_checkbox_copy_1: true,
  question_11_text: "110 Monroe St",
  question_11_text_copy_0: "186 Aspen Road",
  question_12_checkbox: false,
  question_12_checkbox_copy_0: false,
  question_12_text: "New York",
  question_12_text_copy_0: "South Orange",
};

const copy_n = /^(.*)_copy_(\d+)$/;
const result = {};
for (const key in data) {
  const value = data[key];
  const match = key.match(copy_n);
  
  if (match) {
    const copies_key = `${match[1]}_copies`;
    const index = parseInt(match[2], 10);
    result[copies_key] ||= [];
    result[copies_key][index] = { [key]: value };
  } else {
    result[key] = value;
  }
}

console.log(result);

The regex pattern /^(.*)_copy_(\d+)$/ identifies any string that concludes with _copy_ followed by one or more digits. The segment before _copy_ is captured in group 1, while the digits following _copy_ are captured in group 2.

In cases of no match (else situation), we simply assign the value to the corresponding key.

If a match is found (if situation), we first establish the collection key (copies_key) and determine the appropriate index. Subsequently, we validate whether result[copies_key] is already defined (checking its truthiness). If not, we set it as an empty array and proceed to allocate an object at the correct position within the array using the provided index.

Answer №2

To condense the entries of an object into a new object, each key must be checked to see if it has a base key (preceding ""copy") using a RegExp with lookahead. If there is no base key, the key is added directly to the accumulator. If a base key exists, it is added to the appropriate "copies" array (creating one if necessary using Logical nullish assignment ??=) (TS playground).

const fn = obj => Object.entries(obj)
  .reduce((acc, [k, v]) => {
    const [baseKey] = k.match(/.*(?=_copy_)/) ?? [] // get the key from an item with copy
    
    if(!baseKey) acc[k] = v // if no baseKey add the item to the accumulator
    else {
      const copiesKey = `${baseKey}_copies`
      acc[copiesKey] ??= [] // if no copies key add a new one to the accumulator    
      acc[copiesKey].push({ [k]: v }) // create an object and push to the current copies key
    }
    
    return acc
  }, {})
  
const obj = {"question_10":"","question_10a":"","question_11_checkbox":false,"question_11_checkbox_copy_0":false,"question_11_checkbox_copy_1":true,"question_11_text":"110 Monroe St","question_11_text_copy_0":"186 Aspen Road","question_12_checkbox":false,"question_12_checkbox_copy_0":false,"question_12_text":"New York","question_12_text_copy_0":"South Orange"}
const result = fn(obj)

console.log(result)

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

Exploring the implementation of initiating paypal in NestJs using Jest testing framework

Currently, I am creating a test for a method within NestJs that is responsible for initiating a Paypal Payment intent. When I execute either the yarn test:watch or simply yarn test command, the test described below runs successfully and passes. However, up ...

Creating a static Top Bar that remains unaffected by page refreshing using Ajax or any other method can be achieved by implementing JavaScript and CSS

I've designed a sleek top bar for my upcoming website project. Below is the CSS code snippet for creating this clean div bar: .topbar { display:block; width:100%; height:40px; background-color:#f5f5f5; } I'm looking to incorporate a simple .SWF ...

Retrieve the image description using the file_picker_callback and image uploader in Tinymce

TL:DR I am attempting to retrieve the value of the image_description field using JavaScript to include it in my post XHR request Original query: I am utilizing the file_picker_callback type image I have enabled the image_description input field in my ...

collaborate and coordinate a territory among various components on a map

I'm currently working with an array of elements that are being drawn on a canvas. export function useCanvas(){ const canvasRef = useRef(null); const [ elements, setElements] = useState([]); const [ isHover, setIsHover] = useState(false); ...

What's the best way to vertically center a div with a 100% width and a set padding-bottom on the screen?

I am struggling with positioning the following div on my webpage. .div { width:100%; padding-bottom:20%; background-color:blue; } <div class="div"></div> I have been searching for a solution to vertically center this responsive div on my web ...

What is the best way to transmit data via $router.push in Vue.js?

I am currently working on implementing an alert component for a CRUD application using Vue.js. My goal is to pass a message to another component once data has been successfully saved. I attempted to achieve this by passing the data through $router.push lik ...

typescript api overlooking the async await functionality

My controller contains an asynchronous method that is supposed to set a results object. However, I'm facing an issue where instead of waiting for the 'await' to finish executing, the code jumps to the response object call prematurely, leavin ...

Using TypeScript, we can assign a JSON object to an extended class by leveraging the

Task was to include an additional property. I modified a current class by adding a new property, but when I assign a JSON object from the database, the newly added property disappears. Is there a way to correctly assign a JSON object to a TypeScript class ...

What is the process of installing an npm module from a local directory?

I recently downloaded a package from Github at the following link: list.fuzzysearch.js. After unzipping it to a folder, I proceeded to install it in my project directory using the command: npm install Path/to/LocalFolder/list.fuzzysearch.js-master -S Howe ...

Resolving the CORS preflight issue with Loopback API in Redux

My current setup involves a client application running on React-Redux and an API app on Loopback. During local testing, I have the client app on port 8080 and the server app on port 3000. While attempting to test Google OAuth (using the loopback-passport ...

Adjust the positioning of axisLeft labels to the left side

I have incorporated a @nivo/bar chart in my project as shown below: <ResponsiveBar height="400" data={barData} keys={["value"]} indexBy="label" layout="horizontal" axisLeft={{ width ...

The ZIP file downloaded from NodeJS is corrupted and cannot be opened

Currently, I am utilizing the following code to create a MySQL dump in memory, then zip that SQL file with a password from memory and save it to the hard drive so it can be streamed to the client... /* DUMP - database */ var mysqld ...

Concerns with JavaScript Scope

I'm currently working on a function that I need help with. The function seems pretty straightforward to me: function CheckFile(path){ var status = false; $.ajax({ url: "http://mydomain.com/"+path, type: "HEAD", s ...

What is the importance of adding the ".js" extension when importing a custom module in Typescript?

This is a basic test involving async/await, where I have created a module with a simple class to handle delays mymodule.ts: export class foo { public async delay(t: number) { console.log("returning promise"); ...

Tips for breaking up array elements across multiple "tr" tags

In this particular example, I have a Fiddle set up with multiple tr elements displayed within an ng-repeat. My goal is to have three td elements per row. Would it be necessary to use an inner angularjs ng-repeat and split the iconDets array for this purpos ...

Can you clarify the meaning of "int" in this code snippet?

What does the ?: and <I extends any[] = any[]> signify in this context, and how is it utilized? export interface QueryConfig<I extends any[] = any[]> { name?: string; text: string; values?: I; types?: CustomTypesConfig; } ...

Creating unique parent-children category groupings in Excel VBA using collections and dictionaries - how can it be done?

Could someone assist me in understanding how to consolidate data by hierarchical groupings using VBA? PivotTables and tables are not feasible due to user constraints. The data includes three levels of groupings: Parent, Child, and Grain. Parents may have ...

How can I verify if my discord.js bot has the necessary permissions from a server or channel?

I need to verify two things: Determine if my bot has a particular SERVER permission (return true/false based on the presence of that permission) Confirm if my bot possesses a specific CHANNEL permission (return true/false depending o ...

"Discover the process of retrieving a specific element from a JSON array within PL/SQL Oracle 12c

Querying a column in an Oracle 12c table that contains CLOB data, specifically in JSON format under the column name 'dynamic_fields'. The content of the column is structured as follows: { "App": 20187.7", "CTList": "[ {\"line ...

Adding new data to a Chart.js line graph in vue on form submission - A step-by-step guide

I'm struggling with dynamically updating my line chart with new data. I want the chart to refresh every time a user submits a form with new data. Currently, I can add new data to the datasets array in the data function of App.vue, but the chart doesn& ...