I have a series of JSON entries:
[{"num": "1","name_A": "Alex" ,"name_B": "Bob"}, {"num": "2","name_A": "Anne" ,"name_B": "Barbra"}]
I am trying to convert this array of Objects as painlessly as possible into two objects - one with title name_A, and the second with the title name_B. Objects have to contain the title and an array of matching num-name pairs:
[{title: "name_A", names:[{"1", "Alex}, {"2", "Anne"}]}, {title:"name_B", names: [{"1", "Bob"}, {"2", "Barbra"}]}]
At first I tried simply to create two objects by reducing the array of object twice, once for name_A and second time for name_B and later glue everything together:
// get 'names' array
var name_A = objArray.reduce(function(memo, curr) {
memo.push({curr.num, curr.name_A})
return memo;
}, []);
But even this is failing. Why there is no push method for memo if I initialize reduce with an empty array?
And second question, am I on a right track or is there a better way to achieve this?
Comments inline, made a few minor corrections to the expectations.
var input = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }]
var output = input.reduce(function (a, b) {
// construct new objects and set their properties
var i = {};
i[b.num] = b.name_A;
var j = {};
j[b.num] = b.name_B;
// add them to our collection elements
a[0].names.push(i);
a[1].names.push(j);
return a;
// initializing our collection
}, [{ title: "name_A", names: [] }, { title: "name_B", names: [] }]);
// pretty print our output
console.log(JSON.stringify(output, null, " "))
var input = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }]
var output = input.reduce(function (a, b) {
// construct new objects and set their properties
var i = {};
i[b.num] = b.name_A;
var j = {};
j[b.num] = b.name_B;
// add them to our collection elements
a[0].names.push(i);
a[1].names.push(j);
return a;
// initializing our collection
}, [{ title: "name_A", names: [] }, { title: "name_B", names: [] }]);
so.log(output)
<pre id="output"></pre>
<script>
var so = {
log: function(o) {
document.getElementById("output").innerHTML = JSON.stringify(o, null, " ")
}
}
</script>
The problem with your code is that { curr.num, curr.name_A } is not a valid object, it's missing the property names. I've added properties num and name in my code below.
var name_A = [];
var name_B = [];
objArray.forEach(function(curr) {
name_A.push({num: curr.num, name: curr.name_a});
name_B.push({num: curr.num, name: curr.name_B});
});
var result = [
{ title: "name_A" }, names: name_A },
( title: "name_B" }, names: name_B }
];
Also, if you want to make an array out of the results of looping over an array, you should use .map rather than .reduce.
Assuming only property num is fixed. All other properties are treated as data, like name_A or name_B.
var a = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }],
result = [];
a.forEach(function (el) {
var num = el.num;
Object.keys(el).forEach(function (k) {
function tryFindIndexAndSetNames(aa, i) {
if (aa.title === k) {
result[i].names[num] = el[k];
return true;
}
}
if (k !== 'num' && !result.some(tryFindIndexAndSetNames)) {
var o = {};
o[num] = el[k];
result.push({ title: k, names: o });
}
});
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Related
I have the below object obj(coming as a JSON response):
var obj = {
0: {
note: 'test1',
id: 24759045,
createTimeStamp: '2022-08-01T17:05:36.750Z',
},
1: {
note: 'test2',
id: 24759045,
createTimeStamp: '2022-08-01T17:05:51.755Z',
},
note: 'test1',
id: 24759045,
createTimeStamp: '2022-08-01T17:05:36.750Z',
};
I only want the objects with numbers("0" , "1" .. so on) to be pushed in an array.
Below is what I am trying to do:
let items = [];
for (var prop in obj) {
items.push(obj[prop]);
}
console.log(items);
// expected output:
[
{
note: 'test1',
id: 24759045,
createTimeStamp: '2022-08-01T17:05:36.750Z',
},
{
note: 'test2',
id: 24759045,
createTimeStamp: '2022-08-01T17:05:51.755Z',
},
]
Any pointers would be highly appreciated.
A few things to consider here.
Are the numeric keys ordered?
Does the order matter?
Are the numeric keys an index of the item in the array?
Are there any gaps in the numeric keys?
First solution, assuming that the numeric keys are the index in the array.
const items = Object.keys(obj).reduce((acc, key) => {
const index = parseInt(key);
if (Number.isNaN(index)) {
return acc;
}
acc[index] = obj[key];
return acc;
}, []);
Second solution, assuming that order matters, but that the numeric keys are not guaranteed to be contiguous.
const items = Object.keys(obj)
.filter((key) => Number.isNaN(parseInt(key)) === false)
.sort()
.map((key) => obj[key]);
Keep in mind that Object.keys does not guarantee that the keys are ordered alpha-numerically. So if order matters, then you have to sort them.
Third solution, if order doesn't matter.
const items = Object.keys(obj)
.filter((key) => Number.isNaN(parseInt(key)) === false)
.map((key) => obj[key]);
var result = [];
var obj = {
"0": {
"note": "test1",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:36.750Z"
},
"1": {
"note": "test2",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:51.755Z"
},
"note": "test1",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:36.750Z"
}
for (var i in obj)
result.push(obj[i]);
$('#result').html(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="result"></div>
You can achieve this by doing the following steps.
Copied your object below -->
var obj = {
"0": {
"note": "test1",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:36.750Z"
},
"1": {
"note": "test2",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:51.755Z"
},
"note": "test1",
"id": 24759045,
"createTimeStamp": "2022-08-01T17:05:36.750Z"
}
Created new js array -->
var result = [];
Code -->
for (var i in obj)
result.push(obj[i]);
Find the solution from link below as well --> :) :)
https://jsfiddle.net/kavinduxo/95qnpaed/
I think you'll need to get the keys of the object, filter out the non-numeric ones, then map each key to the obj[key]:
var obj={"0":{"note":"test1","id":24759045,
"createTimeStamp":"2022-08-01T17:05:36.750Z"},"1":{"note":"test2","id":24759045,
"createTimeStamp":"2022-08-01T17:05:51.755Z"},
"note":"test1","id":24759045,"createTimeStamp":"2022-08-01T17:05:36.750Z"};
console.log(
Object.keys(obj)
.filter((key) =>!Number.isNaN(parseInt(key)))
.map((key) => obj[key])
)
Hi I am looking to create an array that looks similar to this
const userList = {
123: "Tom",
124: "Michael",
125: "Christin",
};
it contains both value and label, what I tried so far
let raw = []
for (let x in data) {
raw.push(data[x].facility_name : data[x].id)
}
but it didn't work because "," was expected, if someone can help please
You are confusing arrays and objects. You need to add a key to an object not push. I kept it as a for in loop, but a for of loop would make more sense.
const data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
let raw = {};
for (let x in data) {
raw[data[x].id] = data[x].facility_name;
}
console.log(raw);
How I would code it using reduce.
var data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
const raw = data.reduce(function (acc, facility) {
acc[facility.id] = facility.facility_name;
return acc;
}, {})
console.log(raw);
IF your data has nested objects then you might do this:
let raw = {};
for(x in data)
{
raw[data[x].facility_name] = data[x].id;
}
This is useful when you want to get rid of duplicates.
If the fields key in a object is array, change the first value of arrays as a key value pair object in javascript.
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObj(obj) {
let objFields = {};
modifiedObj.fields.forEach(field => objFields[field] = field);
modifiedObj.fields= objFields;
return modifiedObj;
}
var result = this.newObject(obj)
Expected Output
{
item: "item",
sample: "sample"
}
Try this:
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObject(obj) {
let objFields = {};
obj.forEach(e => {
if(e.fields && e.fields.length>0)
objFields[e.fields[0]] = e.fields[0];
});
return objFields;
}
var result = this.newObject(obj);
console.log(result);
Here is a functional approach that makes use of Object.assign(), spread operator, and Array.map() to create the object you need.
const input = [
{ id: 1, fields: ["item", "2", "list"] },
{ id: 2, fields: ["sample", "1", "check"] }
];
const process = (input) => (Object.assign(...input.map(({ fields }) => (
fields.length ? { [fields[0]]: fields[0] } : {}
))));
console.log(process(input));
Your snippet was close, you just needed to clean up the variable names, and then using map makes it a bit neater too:
const obj = [
{id: 1, fields: ["item", "2", "list"]},
{id: 2, fields: ["sample", "1", "check"]}
]
function newObj(inputArray) {
let outputObject = {};
inputArray.map(item => item.fields[0])
.forEach(field => outputObject[field] = field);
return outputObject;
}
var result = newObj(obj)
console.log(result)
Get the corresponding type in the object, and then traverse the array of push objects, but I can't think of a better way to solve the desired result below.
I want a good return as follows:
[{
"id": 1,
"type": "one",
"name": ["apple","apricot"]
},
{
"id": 3,
"type": "two",
"name": ["avocado"]
}]
var result = [{
"id": 1,
"type": "one",
"name": "apple"
}, {
"id": 2,
"type": "one",
"name": "apricot"
},
{
"id": 3,
"type": "two",
"name": "avocado"
}
]
Array.prototype.unique = function() {
var hash = {},
len = this.length,
result = [];
for (var i = 0; i < len; i++) {
if (!hash[this[i].type]) {
result.push(this[i].type);
hash[this[i].type] = true;
}
}
return result;
}
console.log(result)
console.log(result.unique())
var cArr = result.unique()
var arr = []
cArr.forEach(function(prop) {
result.map(function(item) {
if (prop == item.type) {
console.log(item)
arr.push({
...item,
[`user_${item.id}`]: item.user,
})
}
})
})
console.log(arr)
You can do this with reduce quite easily:
var input = [
{ id: 1, type: "one", name: "apple"},
{ id: 2, type: "one", name: "apricot" },
{ id: 3, type: "two", name: "avocado" }
];
// Make sure `unique` doesn't already exist on the Array prototype
if (!('unique' in Array.prototype)) {
Array.prototype.unique = function () {
// iterate over the array
const temp = this.reduce((acc, current) => {
// Desstructure the id, type, and name from the current object
const { id, type, name } = current;
// If an key with the value of `type` doesn't exist
// on the accumulator, add a new object with name set
// to an empty array
acc[type] = acc[type] || { id, type, name: [] };
// Push the name in the current object to the name array
acc[type].name.push(name);
// Return the accumulator for the next iteration
return acc;
// Note: the initial accumulator value is an object
}, {});
// Then simply return the values from the accumulated object
return Object.values(temp);
}
}
console.log(input.unique())
I'm trying to collate some data. I would like to populate an array containing sub arrays, for example, I have some json data that I am iterating over:
{
"name": "name1",
"prices": "209.67"
},
{
"name": "name1",
"prices": "350"
},
{
"name": "name2",
"price": "195.97"
},
I would like to create an array that ends up looking something like the following:
myArray['name1']prices[0] = 209.67,
prices[1] = 350,
['name2']prices[0] = 195.97
I thought that the code below would achieve what I wanted but it doesn't work. It throws an exception. It doesn't seem to recognise the fact that the prices are an array for a given index into the main array. Instead the prices appear at the same level as the names. I want the main array for a given name to contain an inner array of prices.. Does anybody have any idea how I could modify to make this work?
function doStuff() {
var cryptoData = getData();
var datasetValues = {};
datasetValues.names = [];
datasetValues.names.prices = [];
for (var result = 0; result < cryptoData.length; result++) {
var data = cryptoData[result];
if (datasetValues.names.indexOf(data.cryptoname) === -1)
{
datasetValues.names.push(data.cryptoname);
}
// This works
//datasetValues.names.prices.push(data.prices);
// This doesn't!
datasetValues.cryptoNames[data.cryptoname].prices.push(data.prices);
}
}
You could reduce the array by using an object and take a default object if the property is not set. Then push the price.
var data = [{ name: "name1", price: "209.67" }, { name: "name1", price: "350" }, { name: "name2", price: "195.97" }],
result = data.reduce((r, { name, price }) => {
r[name] = r[name] || { name, prices: [] };
r[name].prices.push(+price);
return r;
}, Object.create(null));
console.log(result);
Try this
function parseData(input){
return input.reduce(function(o,i){
o[i.name] = {};
if(!o[i.name]['prices']){
o[i.name]['prices'] = [];
}
o[i.name]['prices'].push(i.prices);
return o;
},{});
}