1

I am trying to merge values from json array that has 2 or more arrays to one json array.

I see many similar questions but I could not find a solution. I tried a long way that did not succeed and there are certainly shorter and more beautiful ways.

I have json object like:

 [
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R01-02"
                },
                "subject": "010-A1"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R33-33"
                },
                "subject": "011-AB"
            }
        }
    ],
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032333"
                },
                "subject": "99-001"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032111"
                },
                "subject": "test-111"
            }
        }
    ]
]

I want the result will be accoding to the subject key, if the subject key value does not exist in the other array the value should be zero.

Expected Result:

[
    [
        {
            "f_measure_function": {
                "value0": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value0": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value0": {
                    "item_type": "ST",
                    "Randomization number": "R01-02"
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": null
                },
                "subject": "010-A1"
            }
        },
        {
            "f_measure_function": {
                "value0": {
                    "item_type": "ST",
                    "Randomization number": "R33-33"
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": null
                },
                "subject": "011-AB"
            }
        },
        {
            "f_measure_function": {
                "value0": {
                    "item_type": "ST",
                    "Randomization number": null
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032333"
                },
                "subject": "99-001"
            }
        },
        {
            "f_measure_function": {
                 "value0": {
                    "item_type": "ST",
                    "Randomization number": null
                },
                "value1": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032111"
                },
                "subject": "test-111"
            }
        }
    ]
]

NOTE: The main array can be inclode more than 2 arrays.

4
  • 2
    So what did you try? It is not hard to do this.. Recursion all the way ;) Commented Jan 30, 2018 at 12:02
  • 1
    you can do something like this const arr1 = [1,2,3]; const arr2 = [3,4,5]; const arr3 = [...arr1, ...arr2]; Commented Jan 30, 2018 at 12:10
  • @GuyT - Thank you, Can you give me an example please? Commented Jan 30, 2018 at 12:59
  • @Majid Thank you for the response. I need to combine them no to concat them. Commented Jan 30, 2018 at 13:05

3 Answers 3

3

I imagine a is your given JSON Array.

let finalArray = []
/* putting all single json in finalArray */
let b = a.map(value => {
    value.map(val => {
        finalArray.push(val)
    })
})

let v = []

finalArray.map((val, idx) => {
    /* filtering all duplicate subjects and putting in to another array v */ 
    v[idx] = finalArray.filter(value => {
        return val.f_measure_function.subject == value.f_measure_function.subject
    })
})

let c = v.map(value => {
     /* creating the final array as you want */
    let va = {"f_measure_function": {}}

    value.forEach((val, idx) => {
        va.f_measure_function["value" + idx] = val.f_measure_function.value
    })

    va.f_measure_function["subject"] = value[0].f_measure_function.subject

    return va
})

console.log(JSON.stringify(c))
Sign up to request clarification or add additional context in comments.

5 Comments

That you for the response!, It seems very nice. But it returns json like:{ "f_measure_function": { "value0": { "item_type": "ST", "Randomization number": "R02-03" }, "value1": { "item_type": "INT", "Serial number of device given to the subject": "13032355" }, "subject": "001-BB" } }
i think its generates output as you described. please tell me where m going wrong !
My mistake, I'm sorry. I returned the json object from a wrong place. Thanks a lot for you!
In the result I have duplicate rows, 2 rows for each subject :(
In the end of your code I added: var uniq = new Set(c.map(e => JSON.stringify(e))); var res = Array.from(uniq).map(e => JSON.parse(e)); and it fixed it :)
1

I'm using an object to help parsing. There are probably way better solutions but this one does the trick!

var JSONstring = document.querySelector('#JSONstring').textContent;

var parsedJSON = JSON.parse(JSONstring);

var results = [];

var resultsObj = {};

var maxValLen = 0;

for (var i=0; i<parsedJSON.length; i++) {
  var array = parsedJSON[i];
  for (var j=0; j<array.length; j++) {
    var item = array[j].f_measure_function;
    if (!resultsObj[item.subject]) {
      resultsObj[item.subject] = [];
    }
    resultsObj[item.subject].push(item.value);
    if (resultsObj[item.subject].length > maxValLen) {
      maxValLen = resultsObj[item.subject].length;
    }
  }
}

for (var subject in resultsObj) {
  var valuesArray = resultsObj[subject];
  var measure = {
    subject: subject
  };
  for (var v=0; v<maxValLen; v++) {
    measure['value'+v] = valuesArray[v] || "null";
  }
  results.push({
    f_measure_function: measure
  })
}

console.log(results);
.hidden {
  display: none;
}
<code id="JSONstring" class="hidden">
[
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R01-02"
                },
                "subject": "010-A1"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R33-33"
                },
                "subject": "011-AB"
            }
        }
    ],
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032333"
                },
                "subject": "99-001"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032111"
                },
                "subject": "test-111"
            }
        }
    ]
]
</code>

5 Comments

Thank you! But in your result there is just value0 for each subject, there should be 2 values for each subject, value0 and value1 (in this case), for each array should be valueX, value0, value1 and so on. Please see my Expected Result
Sorry, it was a typo ... it' fixed.
Thank you very much! It works fine! I prefer another solution that more short.
if there is no value for the specific subject it shoule be null\zero, for example: value1 for "010-A1" subject should be appear with null value
Updated, all working as expected! I thought you were going with another solution. What happened?
0

I divided the work so that it will be more easy to get to the solution with only two arrays in the main array.

About the NOTE indicating that the main array may contain more than two arrays I think you should indicate how the merge will be done since it looks ambiguous.

Hope this will help.

let arr = [
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R02-03"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R01-02"
                },
                "subject": "010-A1"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "ST",
                    "Randomization number": "R33-33"
                },
                "subject": "011-AB"
            }
        }
    ],
    [
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "001-BB"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032355"
                },
                "subject": "002-CC"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032333"
                },
                "subject": "99-001"
            }
        },
        {
            "f_measure_function": {
                "value": {
                    "item_type": "INT",
                    "Serial number of device given to the subject": "13032111"
                },
                "subject": "test-111"
            }
        }
    ]
]

//first array containing the subjects of the first array
let subArr1 = arr[0].map((e) => e.f_measure_function.subject);
//second array containing the subjects of the second array
let subArr2 = arr[1].map((e) => e.f_measure_function.subject);

//our final array that will contain the result
let finalArray = [];

for (let i = 0; i < subArr1.length; i++) {
    
    //the sample object for every new item and we will only modify three values of it
    const newObject = {
        "f_measure_function": {
            "value0": {
                "item_type": "ST",
                "Randomization number": ""
            },
            "value1": {
                "item_type": "INT",
                "Serial number of device given to the subject": ""
            },
            "subject": ""
        }
    };
    let subj = subArr1[i];
    newObject.f_measure_function.value0["Randomization number"] =
    arr[0][i].f_measure_function.value["Randomization number"];
     
    newObject.f_measure_function.subject = subj;  
    
    //test if the subject exists in the second array
    if (subArr2.includes(subj)) {
        newObject.f_measure_function.value1 = arr[1][i]["f_measure_function"]["value"];
    }
    else {
        newObject.f_measure_function.value1["Serial number of device given to the subject"]= null;
    }

    finalArray.push(newObject);
}

for (let i = 0; i < subArr2.length; i++) {
    const newObject = {
        "f_measure_function": {
            "value0": {
                "item_type": "ST",
                "Randomization number": ""
            },
            "value1": {
                "item_type": "INT",
                "Serial number of device given to the subject": ""
            },
            "subject": ""
        }
    };
    let subj =subArr2[i];
    newObject.f_measure_function.value1 = arr[1][i].f_measure_function.value;
    newObject.f_measure_function.subject = subj;
    
    
    //test if the subject exists in the first array
    if (subArr1.includes(subj)) {
        newObject.f_measure_function.value0["Randomization number"] = arr[0][i].f_measure_function.value["Randomization number"];
    }
    else {
        newObject.f_measure_function.value0["Randomization number"] = null;
    }
    //console.log(newObject)
    finalArray.push(newObject); 
}
//console.log(finalArray);

const pre = document.getElementById("result");
pre.innerHTML =JSON.stringify(finalArray,undefined,2);
<pre id="result" class="prettyprint">
    
</pre>

2 Comments

Thank you for your response, , I prefer another solution that more short.
but I thought that the other answers do not give the correct output since there are results without either value0 or value1 .

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.