mm1975
mm1975

Reputation: 1655

Duplicate entire array if an object of the array contains multiple comma seperated values in Javascript

I have an nested array with objects docs, which I first flatten to one level. And I have another flat array called multiValueSelected.

Now I'd like to iterate through all objects of the flattened docs-array and check if the key is also in the multiValueSelected-array.

If so, I would like to copy the entire docs-array for every comma separated value for the specific key, copy all other objects and add the new doc to the table.

With this following approach, I'm able to iterate through all comma separated values, but how can I duplicate the entire docs-array? Thank you for your help.

Example Arrays:

docs [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...]

multiValueSelected {"color, size, ..."}

Expected result for data:

1. {"id" : "test1", "color" : "green", "size" : ""}
2. {"id" : "test1", "color" : "blue", "size" : ""}
3. {"id" : "test1", "color" : "grey", "size" : ""}
4. {"id" : "test1", "color" : "", "size" : "s"}
5. {"id" : "test1", "color" : "", "size" : "m"}

6. {"id" : "test2", "color" : "green", "size" : "l"}

Script:

function importTableau(docs, table) {

  var data = [];
  var importedDocs = 0;

  for (var i = 0; i < docs.length; i++) {

    var flatten = objectFlattenData(docs[i])
    var rec = {}

    for (var key in flatten) {
       // var key deiines the KEY
       // var flatten[key] defines the VALUE without duplicates
       // var flatten defines the CURRENT DOCUMENT

       if (multiValueSelected.indexOf(key) > -1) {
         //console.log('key: ', key, ' flatten: ', flatten[key])
         var flattenString = flatten[key];

         var id = key.replace(/[^A-Za-z0-9_]+/g, '')

         // handling multivalues as seperate doc per value
         var properties = flattenString.split(',');
         var propertiesLength = properties.length;

         for (var i = 0; i < propertiesLength; i++) {
            // Trim the excess whitespace.
            properties[i] = properties[i].replace(/^\s*/, "").replace(/\s*$/, "");
            // Get the single Value
            var singleValue = properties[i]
            console.log(singleValue);

            rec[id] = flatten[singleValue];

            data.push(rec);

         }
         return false;
         
       } else {

         // not selected for handling multivalues as seperate doc
         var id = key.replace(/[^A-Za-z0-9_]+/g, '')
         rec[id] = flatten[key];

       };

    };

    data.push(rec);

  };

  table.appendRows(data);

Upvotes: 0

Views: 217

Answers (2)

It seems a little confusing your expected output, but maybe this is what you want?

let docs = [{
  "id": "test1",
  "color": "green,blue,grey",
  "size": "s,m"
}, {
  "id": "test2",
  "color": "green",
  "size": "l"
}];

let multiValueSelected = ["color", "size"];

let data = [];

for (selected_value of multiValueSelected) {
  for (doc of docs) {
    if (doc.hasOwnProperty(selected_value)) {
      let values = doc[selected_value].split(',');
      for (value of values) {
        let obj = {id: doc.id};
        let keys = Object.keys(doc).filter(k => !['id', selected_value].includes(k));
        keys.map(k => obj[k] = '');
        obj[selected_value] = value;
        data.push(obj);
      }
    }
  }
}

console.log(data)

Upvotes: 1

Simone Ceccarelli
Simone Ceccarelli

Reputation: 201

I really have not understand the question, but if you want to have this:

Input: docs [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...]

Output: multiValueSelected ["color, size, ...", "...."]

as an output you can't have [{"color, size, ..."}] because is not a valid json, a json is a composition of key-value pair and not just only a string

You can do this:

const docs = [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...];

const multiValueSelected = [];

docs.forEach(doc => {
   let currentValue = "";
   Object.keys(doc).forEach(key => {
      if(doc[key].split(',').length > 1)
        currentValue = (currentValue === "") ? key : ", " + key;
   }
   if(currentValue !== "") multiValueSelected.push(currentValue);
}

if you want as output this [{"color": "green,blue,grey" , "size" : "s,m" }, {"....": "....", ....}]

const docs = [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...];
    
const multiValueSelected = [];

docs.forEach(doc => {
   const currentValue = {};
   Object.keys(doc).forEach(key => {
      if(doc[key].split(',').length > 1)
        currentValue[key] = doc[key];
   }
   if(Object.keys(currentValue).length > 0) multiValueSelected.push(currentValue);
}

please let me know if I have not responded to your question

Upvotes: 1

Related Questions