Duplicate entire array if an object of the array contains multiple comma seperated values in Javascript - 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);

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)

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

Related

delete from json conditionally

I have some JSON that looks like this
var js = '{
"person" : {
"firstname" : "Steve",
"lastname" : "Smith",
"other": [
{
"age" : "32",
"deceased" : false
},
{
"age" : "14",
"deceased" : false
},
{
"age" : "421",
"deceased" : false
}
]
}
}'
I know how I delete all of "other" by doing this
var j = JSON.parse(js)
delete j[person.other]
but what I really want is to delete the "other" node with a condition that is age = 14.
The result JSON I am looking for is
{
"person" : {
"firstname" : "Steve",
"lastname" : "Smith",
"other": [
{
"age" : "32",
"deceased" : false
},
{
"age" : "421",
"deceased" : false
}
]
}
}
I have looked at the delete operator here and it does not provide a conditional.
Sorry if this is too simple a question. I am learning.
Thanks
The best approach to this would be not to alter the json, but create another one instead:
const filtered = { ...json, other: json.other.filter(item => item.age !== "14") }
If you really need to alter the json, you can do the following:
let index = json.other.findIndex(item => item.age === "14")
while (index !== -1) {
json.other.splice(index, 1)
index = json.other.findIndex(item => item.age === "14")
}
You can use a filter on the array doing something like
j[person.other].filter(x => x.age != 14)
Doc on how filter works more in depth here :
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

How to display all fields of a nested json in table format using Bootstrap

I want to write a utility which connects to a REST api downloads data in JSON format and then paints the data as nested tables using Bootstrap.
JSON Data -
[
{
"id" : "Id1",
"name" : "Name1",
"orders" : [{"orderId" : "o1", "size" : 34}, {"orderId" : "o2", "size" : 3}]
},
{
"id" : "Id2",
"name" : "Name2",
"orders" : [
{"orderId" : "o3", "size" : 5, "addresses" : [{"addressId" : "a1", "phone" : "1235"}, {"addressId" : "a2", "phone" : 555}]},
{"orderId" : "o4", "size" : 5, "addresses" : [{"addressId" : "a3", "phone" : "1235"}]}
]
}
]
I looked at the sub-table feature of Bootstrap, however it seems that it would need lot of custom code to get this working. Is there a better way to bind the json to table in a generic way?
Edit
After spending some time I was able to achieve this -
As you can see, I could get one level of nesting, however i just need to go one level deep. Any suggestions?
<script>
var $table = $('#table')
function buildTable($el, jsonData) {
var i; var j; var row
var columns = []
var data = []
if(!Array.isArray(jsonData) && jsonData.length == 0) {
return;
}
Object.keys(jsonData[0]).forEach( (k) => {
columns.push({
field: k,
title: k,
sortable: true
})
})
for(var j = 0; j < jsonData.length; j++) {
row = {}
Object.keys(jsonData[j]).forEach( (k) => {
row[k] = jsonData[j][k]
})
data.push(row)
}
$el.bootstrapTable({
columns: columns,
data: data,
detailFilter: function (index, row) {
console.log("detail filter " + Object.values(row))
for(var k in row) {
if(Array.isArray(row[k])){
return true;
}
}
return false;
},
onExpandRow: function (index, row, $detail) {
console.log("expand row keys " + Object.keys(row))
console.log("expand row vals " + Object.values(row))
var newRow = {};
for(var k in row) {
if(Array.isArray(row[k])){
alert('found ' + row[k])
newRow = row[k]
break
}
}
buildTable($detail.html('<table></table>').find('table'), newRow)
}
})
};
var mydata =
[
{
"id": 0,
"name": "test0",
"price": "$0",
"orders" :
[
{
"name" : "ABC",
"size" : 25,
"someList": [{"a":1, "b":2}, {"a":3, "b":4}]
},
{
"name" : "XYZ",
"size" : 50
}
]
}
/* {
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2",
"orders" : [{"name" : "def", "size": 45}]
}*/
];
$(function() {
buildTable($table, mydata)
})

javascript create nested JSON array from array

I have this array :
myArray = [ "Id = 1", "Time = 18:40", "Topic = yyyyyyyyyyyy", "GUEST", "Role = HS", "Infos = Arizona", "Role = GS", "Infos = Arizona", "Role = GS", "Infos = Colorado", "Id = 2","Time = 11:32", "Topic = xoxo", "GUEST", "Role" = "GS", "Infos = California", "Role = CS", "Infos = Maryland", "Role = GS","Infos = Nevada" ];
I want to create a nested JSON array from it:
myJson = [
{
"Id" : "1",
"Time" : "18:40",
"Topic" : "yyyyyyyyyyyy",
"GUEST":
[
{"Role" : "HS",
"Infos" : "Arizona"},
{"Role" : "GS",
"Infos" : "Arizona"},
{"Role" : "HS",
"Infos" : "Colorado"}
]
},
{
"Id" : "2",
"Time" : "11:32",
"Topic" : "xoxo",
"GUEST":
[
{"Role" : "GS",
"Infos" : "California"},
{"Role" : "CS",
"Infos" : "Maryland"},
{"Role" : "GS",
"Infos" : "Nevada"}
]
}
]
How can I do it? tried the code below without success.
myArray = ["Id = 1","Time = 18:40","Topic = yyyyyyyyyyyy","GUEST","Role = HS","Infos = Arizona","Role = GS","Infos = Arizona","Role = GS","Infos = Colorado","Id = 2","Time = 11:32","Topic = xoxo","GUEST","Role" = "GS","Infos = California","Role = CS","Infos = Maryland","Role = GS","Infos = Nevada"];
// Declaring new object
let obj = {};
// Place to remember current level of object
let level;
myJson = [];
for (let item of this.myArray) {
// If it contains an equals
if (item.includes('=')) {
// Split it into two stings
let split = item.split('=');
let key = split[0].trim();
let val = split[1].trim();
// If we're already on a lower level like GUEST3 put it in there
if (level) {
obj[level][key] = val
} else {
// Or just place the new data at the top level
obj[key] = val
}
} else {
// If there's no equals we want to go down a layer
level = item;
myJson.push(obj[item]);
}
}
console.log("myJson : "+ JSON.stringify(myJson));
Another answer is totally right - format you are requesting is totally wrong. If it would have been just going one object deeper when you meet "GUEST" string and create new object in the output when you meet next "Id = \d+" string, you could use something like:
let process = (arr) => {
let path = [];
const data = [];
let o = data;
while (arr && arr.length) {
let item = arr.shift();
let key= null;
let value = null;
if (/Id = \d+/.test(item)) {
o = {};
data.push(o);
let pair = item.split(' = ');
o.Id = pair[1];
}
else if (item == "GUEST") {
o["GUEST"] = {};
o = o["GUEST"]
value = {};
} else {
let pair = item.split(' = ');
o[pair[0]] = pair[1];
}
}
return data;
}
However with this approach your duplicate keys will get overriden like so:
[
{
"Id": "1",
"Time": "18:40",
"Topic": "yyyyyyyyyyyy",
"GUEST": {
"Role": "GS",
"Infos": "Colorado"
}
},
{
"Id": "2",
"Time": "11:32",
"Topic": "xoxo",
"GUEST": {
"Role": "GS",
"Infos": "Nevada"
}
}
]
I think this is a good start and you can fine tune parsing GUEST part up to your liking
JSON's format is wrong.
Key-value pair array is not allowed in JSON.
Key-value pair array cannot have same name key.
Change to the following format (JSON has strict requirements on the format):
myJson = [
{
"Id" : "1",
"Time" : "18:40",
"Topic" : "yyyyyyyyyyyy",
"GUEST":
[
{
"Role" : "HS",
"Infos" : "Arizona"
},
{
"Role" : "GS",
"Infos" : "Arizona"
},
{
"Role" : "HS",
"Infos" : "Colorado"
}
]
}
]

Json Array object to string logic

Not sure if I'm repeating the question or concept.
How do I convert the below sample to the below string format (may not be correct JSON format)
[{ "Name":"Test1","check":"true},{ "Name":"Test2","check":"true},{ "Name":"Test3","check":"false"}]
string format with appending - for false
Expected o/p:
"Test1","Test2","-Test3"
I have tried concatenating, but it always ends up with
"Test1,Test2-Test3"
But I am looking for 3 separate string separated by comma. Any hint would help
You can simply iterate through your array and collect the object in your required format:
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
var result = obj.map(function(x) {
return x.check ? x.Name : "-" + x.Name;
});
document.body.innerHTML = JSON.stringify(result);
Note that I have changed the format of your JSON in order to make it valid.
Just in case if you actually have a string true and false, and you can't change this, you can simply compare it as a string:
var obj = [{
"Name" : "Test1",
"check" : "true"
}, {
"Name" : "Test2",
"check" : "true"
}, {
"Name" : "Test3",
"check" : "false"
}
];
var result = obj.map(function(x) {
return x.check === 'true' ? x.Name : "-" + x.Name;
});
document.body.innerHTML = JSON.stringify(result);
HTML
<div id="output"></div>
Javascript
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
function getNames(){
var length=obj.length;
// alert(length);
var op=[];
for(var i=0;i<obj.length;i++){
// alert(obj[i].Name);
op[i]='"'+obj[i].Name+'"';
}
document.getElementById("output").innerHTML=op;
}
getNames();
Your output is there as expected.
Just loop through the valid JSON array(obj) and append the required values(obj.Name) to the empty string(str) based on the condition(appending '-' for 'false' value of obj.check).
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
var str = '';
for(var x in obj){
str += (obj[x].check === true) ? obj[x].Name : '-'+obj[x].Name;
str += (x != (obj.length-1)) ? ',' : '';
}
alert(str);

How to convert String to Array in MongoDB?

I'm stuck at the situation when the type of an object was changed.
How can I convert this:
{
"_id" : NumberLong(257),
"address" : "street Street, house 50, appartment 508, floor 5"
}
to this:
{
"_id" : NumberLong(257),
"userAddressList" : [{
"street" : "Street",
"house" : "50",
"building" : "",
"appartment " : NumberLong(508),
"entrance" : NumberLong(0),
"floor" : NumberLong(5),
"intercom" : ""
}]
}
using mongo shell?
I need to convert about 350 entries, hope it can be done by the script.
You could try this:
db.collection.find().forEach( function (x) {
lines = x.address.split(",");
obj = {};
userAddressList = [];
lines.forEach( function (address){
addressArray = address.replace(/^\s\s*/, '').replace(/\s\s*$/, '').split(" ");
obj[addressArray[0]] = !isNaN(parseInt(addressArray[1])) ? parseInt(addressArray[1]) : addressArray[1];
});
obj.building = "";
obj.intercom = "";
userAddressList.push(obj);
x.userAddressList = userAddressList; // convert field to string
db.collection.save(x);
});
you can use a foreach in the update like this
db.test.find( { } ).forEach( function (x) {
x.userAddressList = x.address.split(" ");
db.test.save(x);
});

Categories

Resources