Related
I have an object in an array called "Person".
Within the object "Person", there is an array called "info".
My goal is to get all the values with the prefix "age:" in an array "info" when filtering by "gender:male". So, my desired output will be 1 to 9 because I want also to remove duplicates.
Below is my code but the results are only two values (1 and 4). Maybe the output is one value per person.
I spent a lot of hours playing the code but no luck. That's why I bring my problem here hoping anybody who is an expert on this can help me.
<script>
var array = [
{
"person": {
"info": [
"age:1",
"age:2",
"age:3",
"age:4",
"age:5",
"age:6",
"gender:male"
]
},
"person": {
"info": [
"age:4",
"age:5",
"age:6",
"age:7",
"age:8",
"age:9",
"gender:male"
]
},
"person": {
"info": [
"age:8",
"age:9",
"age:10",
"age:11",
"age:12",
"age:13",
"gender:female"
]
}
}
]
var filteredAges = [];
for (i = 0; i < array.length; i++) {
var infoGroup = array[i].person.info,
ageGroup = [];
for (j = 0; j < infoGroup.length; j++) {
ageGroup.push(infoGroup[j]);
var ageInfo = ageGroup.find(ages => ages.includes('age:'));
};
if (ageInfo) {
if (filteredAges.indexOf(ageInfo) == -1) {
filteredAges.push(ageInfo)
}
}
}
for (i = 0;i < filteredAges.length; i++) {
console.log(filteredAges[i]);
}
</script>
Seems like all your object keys are just person i.e
[
{
person: {...},
person: {...},
person: {...}
}
]
So when the variable array is evaluated it just has one person
You need to restructure your data maybe like below or something similar
Example - 1
[
{ person: {...} },
{ person: {...} },
{ person: {...} },
]
Example - 2
[
[ { person: {...} } ],
[ { person: {...} } ],
[ { person: {...} } ]
]
After fixing this you can try debugging your problem
If you want to get all items in info array that has "age:"
you can use filter like this
const ageInfos = [
"age:8", "age:9",
"age:10", "age:11",
"age:12", "age:13",
"gender:female"
].filter(x => x.startsWith("age:"))
Your output - ageInfos will be
["age:8", "age:9", "age:10", "age:11", "age:12", "age:13"]
You can also use Set to only collect unique strings or just push everything to an array and later use Set to return only unique values like this
const arrayWithDuplicates = ['a', 1, 'a', 2, '1'];
const unique = [...new Set(arrayWithDuplicates)];
console.log(unique); // unique is ['a', 1, 2, '1']
First of all, your JSON is wrong. You just overright person object.
Data structure is really awful, I would recommend you to rethink it.
Assuming person will not be overwritten I came up with this solution.
var array = [
{
"person": {
"info": [
"age:1",
"age:2",
"age:3",
"age:4",
"age:5",
"age:6",
"gender:male"
]
},
"person1": {
"info": [
"age:4",
"age:5",
"age:6",
"age:7",
"age:8",
"age:9",
"gender:male"
]
},
"person2": {
"info": [
"age:8",
"age:9",
"age:10",
"age:11",
"age:12",
"age:13",
"gender:female"
]
}
}
]
let agesArray = []
let ages = []
array.forEach((peopleObj) => {
for (const index in peopleObj) {
ages = peopleObj[index].info.map((age) => {
const ageNumber = age.split(':')[1]
if (parseInt(ageNumber)) {
return ageNumber
}
}).filter(val => !!val)
agesArray = [...agesArray, ...ages]
}
})
Thanks a lot guys. I'll apply all of your ideas and try if it can solve my problem.
I am trying to loop through the following array but did not succeed,
is my approach correct?
I have done many changes to my code it might be not as it was
my try :
var gender = ["men", "women"];
var category = [
"topwear",
"bottomwear",
"indianwear",
"westernwear",
];
for (var i = 0; i < categories.length; i++) {
for (var g = 0; g < gender.length; g++) {
for (j = 0; j < categories[i][gender[g]].length; j++) {
for (var c = 0; c < category.length; c++) {
console.log("=======category========", category[c]);
for (k = 0; k < categories[i][gender[g]][j][category[c]].length; k++) {
console.log(categories[i][gender[g]][j][category[c]][k]);
}
}
}
}
}
the array :
[
{
men: [
{
topwear: [
"men-topwear",
"men-tshirts",
"men-casual-shirts",
"men-formal-shirts",
"men-sweatshirts",
"men-sweaters",
"men-jackets",
"men-blazers",
"men-suits",
"rain-jacket",
],
},
{
bottomwear: [
"men-jeans",
"men-casual-trousers",
"men-formal-trousers",
"mens-shorts",
"men-trackpants",
"men-innerwear",
"men-briefs-and-trunks",
"men-boxers",
"men-innerwear-vests",
"men-nightwear",
"men-thermals",
],
},
],
},
{
women: [
{
indianwear: [
"women-kurtas-kurtis-suits",
"ethnic-tops",
"ethnic-wear-dresses-menu",
"women-ethnic-bottomwear?f=categories%3AChuridar%2CLeggings%2CSalwar",
"skirts-palazzos",
"saree",
"dress-material",
"lehenga-choli",
"dupatta-shawl",
"women-ethnic-wear-jackets",
"dresses?f=Gender%3Amen%20women%2Cwomen",
"jumpsuits?f=Gender%3Amen%20women%2Cwomen",
],
},
{
westernwear: [
"women-shirts-tops-tees",
"women-jeans-jeggings",
"women-trousers",
"women-shorts-skirts",
"women-shrugs",
"women-sweaters-sweatshirts",
"women-jackets-coats",
"women-blazers-waistcoats",
],
},
],
},
];
I need to get the names within the array.
coz i need to use it in the code which i am going to write inside the inner
most loop.
thanks in advance
Your code expects each object in the array to have both men and women properties. But these properties are in separate array elements. So you need to check whether the property exists before trying to loop over its elements. Otherwise you'll try to get the length of an undefined property.
Similarly, each object in the men or women array has just a single property, not all the properties in the category array.
Looping will be much easier if you assign variables to the current element of the array, so you don't need long expressions with lots of indexes like categories[i][gender[g]][j][category[c]][k]. And using forEach() will simplify this.
var gender = ["men", "women"];
var category = [
"topwear",
"bottomwear",
"indianwear",
"westernwear",
];
var categories = [{
men: [{
topwear: [
"men-topwear",
"men-tshirts",
"men-casual-shirts",
"men-formal-shirts",
"men-sweatshirts",
"men-sweaters",
"men-jackets",
"men-blazers",
"men-suits",
"rain-jacket",
],
},
{
bottomwear: [
"men-jeans",
"men-casual-trousers",
"men-formal-trousers",
"mens-shorts",
"men-trackpants",
"men-innerwear",
"men-briefs-and-trunks",
"men-boxers",
"men-innerwear-vests",
"men-nightwear",
"men-thermals",
],
},
],
},
{
women: [{
indianwear: [
"women-kurtas-kurtis-suits",
"ethnic-tops",
"ethnic-wear-dresses-menu",
"women-ethnic-bottomwear?f=categories%3AChuridar%2CLeggings%2CSalwar",
"skirts-palazzos",
"saree",
"dress-material",
"lehenga-choli",
"dupatta-shawl",
"women-ethnic-wear-jackets",
"dresses?f=Gender%3Amen%20women%2Cwomen",
"jumpsuits?f=Gender%3Amen%20women%2Cwomen",
],
},
{
westernwear: [
"women-shirts-tops-tees",
"women-jeans-jeggings",
"women-trousers",
"women-shorts-skirts",
"women-shrugs",
"women-sweaters-sweatshirts",
"women-jackets-coats",
"women-blazers-waistcoats",
],
},
],
},
];
categories.forEach(catItem =>
gender.forEach(genItem => {
if (catItem[genItem]) {
category.forEach(cat => {
console.log("=======category========", cat);
catItem[genItem].forEach(i => {
if (i[cat]) {
i[cat].forEach(x => console.log(x));
}
});
});
}
})
);
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"
}
]
I have an object in this format:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
I want to transform it into this:
var request = {
"student": [
{
"name": "Tom",
"age": 12
},
{
"name": "Jack",
"age": 13
}
]
}
I tried doing it this way:
var response = [];
var keysCount = req.result[0].length;
var responseCount = req.result.length - 1;
var i = 0,
j = 0,
key;
for (j = 0; j < responseCount; j++) {
for (i = 0; i < keysCount; i++) {
key = req.result[0][i];
response[j][key] = req.result[j + 1][i];
}
}
return response;
But, it is not working as expected.
It's a matter of looping through the first array and creating an array of objects for all the remaining arrays, using values at matching indexes to create properties on object:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// Get the header array
var headers = request.student[0];
// Create the new array but mapping the other entries...
var newArray = request.student.slice(1).map(function(entry) {
// Create an object
var newEntry = {};
// Fill it in with the values at matching indexes
headers.forEach(function(name, index) {
newEntry[name] = entry[index];
});
// Return the new object
return newEntry;
});
console.log(newArray);
I would make a small function tabularize that takes an array of data where the first element is an array of headers, and the remaining elements are the rows
Code that follows uses ES6. If you need ES5 support, you can safely transpile this code using a tool like babel.
// your original data
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your transformed object
var request2 = {student: tabularize(request.student)};
// log the output
console.log(request2);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Or you can create the request object with the intended shape by passing the tabular data directly into the tabularize function at the time of object creation
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your request object
var request = {
student: tabularize([
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
])
};
// log the output
console.log(request);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Let's start off by writing a little function just to create an object from two arrays, one of keys and one of their values:
function makeObjectFromPairs(keys, values) {
var object = {};
for (var i = 0; i < keys.length; i++) {
object[keys[i]] = values[i];
}
return object;
}
// makeObjectFromPairs(['a', 'b'], [1, 2]) === {a: 1, b: 2}
Now we can use the first element of the students array as the keys, and each of the remaining elements as the values.
var keys = students[0];
var result = [];
for (var i = 1; i < students.length; i++) {
result.push(makeObjectFromPairs(keys, students[i]);
}
You could use Array#map etc. as an alternative for the loops, but perhaps this basic approach is more accessible.
Fixing your original code
Since you made a valiant effort to solve this yourself, let's review your code and see where you went wrong. The key point is that you are not initializing each element in your output to an empty object before starting to add key/value pairs to it.
for (j = 0; j < responseCount; j++) {
// Here, you need to initialize the response element to an empty object.
response[j] = {};
Another solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var response = {};
var students = [];
var responseCount = request.student.length - 1;
var j = 0,
key;
for (j = 0; j < responseCount; j++) {
var student = {};
request.student[0].forEach(function(name, index) {
student[name] = request.student[1 + j][index];
});
students.push(student)
}
response["students"] = students;
console.log(response); // {"students":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Lodash solution
var keys = _.head(request.student);
var valueGroups = _.flatten(_.zip(_.tail(request.student)));
var studentObjects = valueGroups.map(function(values){
return values.reduce(function(obj, value, index){
obj[keys[index]] = value;
return obj;
}, {});
});
console.log(studentObjects);
https://jsfiddle.net/mjL9c7wt/
Simple Javascript solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var students = [];
for(var x = 1; x<request.student.length;x++)
{
var temp = { 'name' : request.student[x][0],
'age' : request.student[x][1]
}
students.push(temp);
}
request = { 'students' : students}
console.log(request);
I want to iterate over a JSON in javasacript and create something like this as output
{
"seriesData": [
{
"name": "John",
"data": [
5,
3,
4
]
},
{
"name": "Jane",
"data": [
2,
2,
3
]
},
{
"name": "Joe",
"data": [
3,
4,
4
]
}
]
}
So, I essentially need to add values in data array for each key inside my for loop.
Input looks like:
{"Records":[{"name":"Jan'10","users":[{"name":"John","y":5},{"name":"Jane","y":2},{"name":"Joe","y":3}]},{"name":"Jan'10","users":[{"name":"John","y":3},{"name":"Jane","y":2},{"name":"Joe","y":4}]},{"name":"Jan'10","users":[{"name":"John","y":4},{"name":"Jane","y":3},{"name":"Joe","y":4}]}]};
Can someone please suggest how can this be achieved.
you could try something like this:
var dataList = {};
function addData(name){
if( dataList[name] == undefined)
dataList[name] = [];
for (var i = 1; i < arguments.length; i++) {
dataList[name].push(arguments[i]);
}
}
function packData(){
var pack = []
for(var e in dataList){
pack.push({
name: e,
data:dataList[e].sort(function(a,b){return a-b})
});
}
return pack;
}
addData("Joe", 1);
addData("Jan", 2, 10);
addData("Joe", 3, 5, 10, 18, 500);
addData("Jan", 4);
addData("Joe", 5);
addData("Jan", 6);
console.log( packData() );
use addData(name, data); to append data to a name and afterwards pack this data with packData()
EDIT:
Sry switched to PHP for a while... fixed the script XD