I have the following input array(It's a Javascript Object[] Array response):
[
{index:1, headerCSV:"Name", dataFields: ["Name", "Id"]},
{index:2, headerCSV:"Id", dataFields: ["Test", "Test 1"]},
{index:3, headerCSV:"fname", dataFields: ["Test", "Test 1"]},
{index:4, headerCSV:"lname", dataFields: []},
]
I am trying to convert it to the following array:
[
{"header" : 1, "field" :"Name"},
{"header" : 1, "field" :"Id"},
{"header" : 2, "field" :"Test"},
{"header" : 2, "field" :"Test 1"},
{"header" : 3, "field" :"Test"},
{"header" : 3, "field" :"Test 1"}
]
In the result array I'll need to put in the header with the input array index and in the field I'll need to construct using the array of the dataFields array of the input array. I have tried with the following code:
var CSVHeadersAndFields = /* The input array */;
var headerFieldMappingJSON = [];
for(var i=0; i<CSVHeadersAndFields.length;i++) {
headerFieldMappingJSON[i] = {};
var selectedFields = CSVHeadersAndFields[i].dataFields;
for(var j=0; j<selectedFields.length;j++) {
headerFieldMappingJSON[i].header = CSVHeadersAndFields[i].index;
headerFieldMappingJSON[i].field = selectedFields[j];
}
}
But I have got the following result:
[
{"header":1,"field":"Name"},
{"header":2,"field":"Test"},
{"header":3,"field":"Test"},
{}
]
I suspect form the for loop 1st iteration value is replaced by the second iteration and also I'll need to avoid to construct the output array mapping from the empty array of dataFields from the input array.
How to make a correct algorithm to convert the array?
Make a separate iterator index for the result array. Or just push to the result array instead of adding values by index:
var CSVHeadersAndFields = /* The array from question */;
var headerFieldMappingJSON = [];
for(var i = 0; i < CSVHeadersAndFields.length; i++) {
var selectedFields = CSVHeadersAndFields[i].dataFields;
for(var j = 0; j < selectedFields.length; j++) {
headerFieldMappingJSON.push({
header: CSVHeadersAndFields[i].index,
field: selectedFields[j]
});
}
}
The same example but cleaner:
var input = /* The array from question */;
var output = [];
input.forEach(function (csvRow) {
csvRow.dataFields.forEach(function (field) {
output.push({
header: csvRow.index,
field: field
});
});
});
You can try following approach:
Logic:
Loop over data and push data in an array based on parsing logic.
In every iteration, you can again loop over obj.dataFields and create object for every field.
You can then merge this output array to original output list.
var data = [
{index:1, headerCSV:"Name", dataFields: ["Name", "Id"] },
{index:2, headerCSV:"Id", dataFields: ["Test", "Test 1"] },
{index:3, headerCSV:"fname", dataFields: ["Test", "Test 1"] },
{index:4, headerCSV:"lname", dataFields: []}
];
var output = data.reduce((acc, obj) => {
const header = obj.index;
return acc.concat( obj.dataFields.map((field) => ({ header, field}) ))
}, []);
console.log(output)
The code below will give you one result object per dataField and use the index property from CSVHeadersAndFields as the header property for each of them.
const result = CSVHeadersAndFields.map(item =>
item.dataFields.map(field => {
return {
header: item.index,
field
}
})
);
here is the simpler code:
var CSVHeadersAndFields = [ {index:1, headerCSV:"Name", dataFields: ["Name","Id"]},
{index:2, headerCSV:"Id", dataFields:["Test","Test 1"]},{index:3, headerCSV:"fname", dataFields:["Test","Test 1"]}, {index:4, headerCSV:"lname", dataFields:[]};
var headerFieldMappingJSON = [];
for(var CSVHeadersAndField of CSVHeadersAndFields ) {
for(var dataFieldVal of CSVHeadersAndField['dataFields']){
headerFieldMappingJSON.push({'header': CSVHeadersAndField['index'], 'field': dataFieldVal })
}
}
output:
[
{
"header": 1,
"field": "Name"
},
{
"header": 1,
"field": "Id"
},
{
"header": 2,
"field": "Test"
},
{
"header": 2,
"field": "Test 1"
},
{
"header": 3,
"field": "Test"
},
{
"header": 3,
"field": "Test 1"
}
]
Related
I have an array. If the name value is empty, I need to change it to the end of the array, how can I do that in Javascript?
ex:
const data : [
{
id:0,
name:"gorkem"
}
{
id:1,
name:""
}
{
id:2,
name:"ahmet"
}
];
Replace
const data : [
{
id:0,
name:"gorkem"
}
{
id:2,
name:"ahmet"
}
{
id:1,
name:""
}
];
Use two calls to filter, one to get the items with non-empty name, the other with the empty names. Then concatenate these two arrays.
let non_empty = data.filter(el => el.name);
let empty = data.filter(el => !el.name);
let result = non_empty.concat(empty);
You could just sort the array based on the "truthiness" of the "name".
const data = [{
id:0,
name:"gorkem"
}, {
id:1,
name:""
}, {
id:2,
name:"ahmet"
}];
console.log(data.sort((a,b)=>!a.name - !b.name));
Above, we are basically abusing the fact that an empty string is a falsy value which is equivalent to 0, while a non empty string is truthy, which is equivalent to 1. Each are negated with a "!" to get the reversed sort order you are after and to actually treat them as booleans.
result :
[
{
"id": 0,
"name": "gorkem"
},
{
"id": 2,
"name": "ahmet"
},
{
"id": 1,
"name": ""
}
]
First of all you need to have a valid array:
const data = [{
id:0,
name:"gorkem"
}, {
id:1,
name:""
}, {
id:2,
name:"ahmet"
}];
So, starting with that you can use a loop to remove empty name element and add to the end:
for (let i = 0; i < data.length; i++) {
if (data[i].name === '') {
let val = data[i];
data.splice(i, 1);
data.push(val);
}
}
I'm trying to create entites in Dialogflow using node.js. The entity values will come from a JSON file. I'm currently testing it using postman. However, the entity values are not being separated and being combined in only one line. How do I fix this? Thank you
This is my sample JSON file that is being sent.
{
"Entity_Values": [
{
"Value": "One",
"Synonym":["Solo","1"]},
{
"Value": "Two",
"Synonym":["Double","2"]}
],
"Entity_Name": "Sample"}
This is what I have so far:
function createEntity (inputEntityobj, EntityName) {
const promises = [];
let entity_values = {value:[], synonyms:[]};
let inputEntity_values = [inputEntityobj];
for (i = 0; i < inputEntityobj.length; ++i) {
let inputEntity_values = [inputEntityobj[i].Value];
let inputEntity_synonym = [inputEntityobj[i].Synonym];
entity_values.value.push(inputEntity_values);
entity_values.synonyms.push(inputEntity_synonym);
}
const sizeRequest = {
parent: agentPath,
entityType: {
displayName: (EntityName),
kind: 'KIND_MAP',
autoExpansionMode: 'AUTO_EXPANSION_MODE_UNSPECIFIED',
enableFuzzyExtraction: true,
entities: [entity_values],
},
};
This code outputs
value: [ [ 'One' ], [ 'Two' ] ], synonyms: [ [ [Array] ], [ [Array] ] ]
And in Dialogflow, these are all in one entity entry instead of being in two separate entries.
Your JSON input is almost identical to the required object format for entities (reference) and will only need a little bit of tweaking to make it work. Using your JSON, I renamed the Value and Synonym to value and synonyms. Loop through Entity_values and push the key value pair to list entityVal and use it for the request.
'use strict';
const dialogflow = require('#google-cloud/dialogflow').v2;
var inputEntityObj = {
"Entity_Values": [
{
"Value": "One",
"Synonym":["Solo","1"]},
{
"Value": "Two",
"Synonym":["Double","2"]}
],
"Entity_Name": "Sample"};
var obj = inputEntityObj['Entity_Values'];
// rename keys
var res = obj.map(item => {
item.value= item.Value;
item.synonyms= item.Synonym;
delete item.Value;
delete item.Synonym;
return item;
});
var entityVal =[];
for (const entity in res){
entityVal.push(res[entity]);
}
var projectId = 'your-project-id';
var entityType = { displayName: 'test', //hard coded value for testing purposes
kind: 'KIND_MAP',
autoExpansionMode: 'AUTO_EXPANSION_MODE_UNSPECIFIED',
enableFuzzyExtraction: true,
entities: entityVal,
};
var parent = `projects/${projectId}/agent`;
var request = { parent: parent,
entityType: entityType
};
console.log(JSON.stringify(request, null, 2));
const client = new dialogflow.EntityTypesClient();
client.createEntityType(request);
See testing done below:
request structure:
{
"parent": "projects/your-project-id/agent",
"entityType": {
"displayName": "test",
"kind": "KIND_MAP",
"autoExpansionMode": "AUTO_EXPANSION_MODE_UNSPECIFIED",
"enableFuzzyExtraction": true,
"entities": [
{
"value": "One",
"synonyms": [
"Solo",
"1"
]
},
{
"value": "Two",
"synonyms": [
"Double",
"2"
]
}
]
}
}
Created entity in dialogflow:
I have a json format and want to convert
Here are my script. I had tried but cannot get the correct results. Please give some advice, thanks and appreciate.
function groupBy() {
var list = [{
"id": "009",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "007",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "006",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "pm1",
"Nm": "Model 1",
"pid": "puma"
},
{
"id": "003",
"Nm": "Model 1",
"pid": "adidas"
},
{
"id": "pm5",
"Nm": "Model 1",
"pid": "puma"
},
{
"id": "aj1",
"Nm": "Model 1",
"pid": "nike"
},
{
"id": "aj2",
"Nm": "Model 1",
"pid": "nike"
}
];
var output = [];
for (var i = 0; i < list.length; i++) {
if (list[i].pid != undefined) {
output.push(list[i]);
}
}
console.log(output);
}
groupBy();
One option is to reduce into an object indexed by pids, whose values are arrays. On each iteration, create the array at the appropriate property if it doesn't exist, and then push to that array:
var list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
console.log(
list.reduce((a, item) => {
const { pid } = item;
if (!a[pid]) a[pid] = [];
a[pid].push(item);
return a;
}, {})
);
You're pretty close there. But [] is to initialize an array instead of an object in javascript. In JS, it's {}.
Following is one of many ways you can accomplish this.
function groupBy() {
var list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
// Initialize output as an object
var output = {};
for (var i = 0; i < list.length; i++){
// 'objectKey' is where you group the list item by its 'pid'
var objectKey = list[i].pid;
// If there's a 'pid' in the list item, but 'output' is not an array yet, then..
if (objectKey && !output.hasOwnProperty(objectKey)){
// Initialize output.group to be an array
output[ objectKey ] = [];
}
// Then finally, store the list into output's group that we created above.
output[ objectKey ].push( list[i] );
}
console.log(output);
}
groupBy();
Use this method for your any group by
const groupBy = function(arr, prop) {
return arr.reduce(function(groups, item) {
const val = item[prop]
groups[val] = groups[val] || []
groups[val].push(item)
return groups
}, {})
}
const list = [
{"id":"009","Nm":"Model 1","pid":"adidas"},
{"id":"007","Nm":"Model 1","pid":"adidas"},
{"id":"006","Nm":"Model 1","pid":"adidas"},
{"id":"pm1","Nm":"Model 1","pid":"puma"},
{"id":"003","Nm":"Model 1","pid":"adidas"},
{"id":"pm5","Nm":"Model 1","pid":"puma"},
{"id":"aj1","Nm":"Model 1","pid":"nike"},
{"id":"aj2","Nm":"Model 1","pid":"nike"}
];
const groupOutput = groupBy(list, 'pid');
You pass your key as second argument into groupBy for group by.
I have the following array list.
var data = [ "USA", "Denmark", "London"];
I need to convert it in this form
var data = [
{ "id" : 1, "label": "USA" },
{ "id" : 2, "label": "Denmark" },
{ "id" : 3, "label": "London" }
];
Can anyone please let me know how to achieve this.
Pretty easy using Array.map (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
var formatted = data.map(function(country, index) {
return { id: (index + 1), label: country }
});
Simple version:
var convertedData = []
for (var i in data){
convertedData.push({id: i+1, label: data[i]});
}
data = convertedData; //if you want to overwrite data variable
You can use forEach to loop through the data array
var data = [ "USA", "Denmark", "London"];
var demArray =[];
data.forEach(function(item,index){
demArray.push({
id:index+1,
label:item
})
})
console.log(demArray)
JSFIDDLE
Underscore way (for old browsers without Array.map support):
var res = _.map(data, function(p, i){
return {id: i + 1, label: p};
});
I have data that's in this format:
{
"columns": [
{
"values": [
{
"data": [
"Project Name",
"Owner",
"Creation Date",
"Completed Tasks"
]
}
]
}
],
"rows": [
{
"values": [
{
"data": [
"My Project 1",
"Franklin",
"7/1/2015",
"387"
]
}
]
},
{
"values": [
{
"data": [
"My Project 2",
"Beth",
"7/12/2015",
"402"
]
}
]
}
]
}
Is there some super short/easy way I can format it like so:
{
"projects": [
{
"projectName": "My Project 1",
"owner": "Franklin",
"creationDate": "7/1/2015",
"completedTasks": "387"
},
{
"projectName": "My Project 2",
"owner": "Beth",
"creationDate": "7/12/2015",
"completedTasks": "402"
}
]
}
I've already got the column name translation code:
r = s.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
}).replace(/[\(\)\s]/g, '');
Before I dive into this with a bunch of forEach loops, I was wondering if there was a super quick way to transform this. I'm open to using libraries such as Underscore.
function translate(str) {
return str.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
})
.replace(/[\(\)\s]/g, '');
}
function newFormat(obj) {
// grab the column names
var colNames = obj.columns[0].values[0].data;
// create a new temporary array
var out = [];
var rows = obj.rows;
// loop over the rows
rows.forEach(function (row) {
var record = row.values[0].data;
// create a new object, loop over the existing array elements
// and add them to the object using the column names as keys
var newRec = {};
for (var i = 0, l = record.length; i < l; i++) {
newRec[translate(colNames[i])] = record[i];
}
// push the new object to the array
out.push(newRec);
});
// return the final object
return { projects: out };
}
DEMO
There is no easy way, and this is really not that complex of an operation, even using for loops. I don't know why you would want to use regex to do this.
I would start with reading out the column values into a numerically indexed array.
So something like:
var sourceData = JSON.parse(yourJSONstring);
var columns = sourceData.columns[0].values[0].data;
Now you have a convenient way to start building your desired object. You can use the columns array created above to provide property key labels in your final object.
var sourceRows = sourceData.rows;
var finalData = {
"projects": []
};
// iterate through rows and write to object
for (i = 0; i < sourceRows.length; i++) {
var sourceRow = sourceRows[i].values.data;
// load data from row in finalData object
for (j = 0; j < sourceRow.length; j++) {
finalData.projects[i][columns[j]] = sourceRow[j];
}
}
That should do the trick for you.