I want to create new key from child values inside the json with ES6/ES5. I tried with arrow functions but i couldn't get the result. Firstly you can see my part of json in below,
[
{
matchId:307,
matchStatusId:5,
matchHomeScore:0,
matchAwayScore:0,
matchTime:0,
homeClubId:608,
homeClub:{
clubId:608,
clubName:"Annaba"
},
awayClubId:609,
awayClub:{
clubId:609,
clubName:"Bazer Sakhra"
},
leagues:[
{
leagueId:65,
parentLeagueId:null,
leagueName:"ALGERIA"
},
{
leagueId:66,
parentLeagueId:65,
leagueName:"Algeria Cup"
}
]
},
]
I want to create new parent key. It will get the values from values of child items and it will combine. Child item numbers changeable. Not everytime 2 items.
leaguesGeneral:"ALGERIA - Algeria Cup"
leaguesGeneral:"ALGERIA - Algeria Cup"
leagues: [
{
leagueId:65,
parentLeagueId:null,
leagueName:"ALGERIA"
},
{
leagueId:66,
parentLeagueId:65,
leagueName:"Algeria Cup"
}
]
I found this method. But it combines everything from the parent.
data = data.map(function (x) {
var keys = Object.keys(x);
x.newKeyValue = keys.map(key => x[key]).join('-');
return x;
});
The leaguesGeneral key can be added to each object in the array using
o.leagues.map(({ leagueName }) => leagueName).join(' - ')
const data = [
{
matchId:307,
matchStatusId:5,
matchHomeScore:0,
matchAwayScore:0,
matchTime:0,
homeClubId:608,
homeClub:{
clubId:608,
clubName:"Annaba"
},
awayClubId:609,
awayClub:{
clubId:609,
clubName:"Bazer Sakhra"
},
leagues:[
{
leagueId:65,
parentLeagueId:null,
leagueName:"ALGERIA"
},
{
leagueId:66,
parentLeagueId:65,
leagueName:"Algeria Cup"
}
]
},
];
const result = data.map(o => {
if (o.leagues) {
o.leaguesGeneral = o.leagues.map(({ leagueName }) => leagueName).join(' - ');
}
return o;
})
console.log(result)
Related
I have an array that is made from another array with the map method in JavaScript:
response = initialResponse.data.Resurs.map((item)=>({
KomRes:item.Kom,
levels:
[
...item.NumList.map((item)=>(
{
KomRes:item.Number,
})),
...item.SerList.map((item,index3)=>({
KomRes:"Serial: " + item.Ser,
})),
]}));
So, I have an array of 1 object and one array of objects. Now, I want to add indexes so that the parent object and all of its child objects have different indexes. One example would be:
[
{
KomRes:"abc"
id:1 // ==> Here the id is different to the levels objects id-s
levels:[{KomRes:"cde",id:2},{KomRes:"cdef",id:3}]
},
{
KomRes:"dfr"
id:4 // ==> Here the id is different to the levels objects id-s
levels:[{KomRes:"dsf",id:5},{KomRes:"sgsd",id:6}]
},
{
KomRes:"fgr"
id:7 // ==> Here the id is different to the levels objects id-s
levels:[{KomRes:"zizu",id:8},{KomRes:"hkl",id:9}]
},
]
As you can see, all of the objects have different ids (indexes). How can I achieve that?
I tried to add index to map method, but don't know how to achieve that with child map methods:
response = initialResponse.data.Resurs.map((item,index)=>({
KomRes:item.Kom,
id:index,
levels:
[
...item.NumList.map((item)=>(
{
KomRes:item.Number,
})),
...item.SerList.map((item,index3)=>({
KomRes:"Serial: " + item.Ser,
})),
]}));
Define a counter variable outside the function then on each iteration each object is given id property with an incremented value of the counter variable. Should there be any sub-arrays, they will be handled recursively by calling itself and passing in the sub-array.
const data=[{KomRes:"abc",id:null,levels:[{KomRes:"cde",id:null},{KomRes:"cdef",id:null}]},{KomRes:"ghi",id:null,levels:[{KomRes:"ijk",id:null},{KomRes:"ijkl",id:null}]},{KomRes:"mno",id:null,levels:[{KomRes:"omn",id:null},{KomRes:"omnp",id:null}]}];
let idx = 1;
function flatIndex(array) {
return array.map(obj => {
if (!obj.id) {
obj.id = idx++;
}
Object.values(obj).map(v => {
if (Array.isArray(v)) {
return flatIndex(v);
}
return obj;
});
return obj;
});
}
console.log(flatIndex(data));
Not sure if I understand well what you want to achieve, but you can declare a variable out of the scope and increment it along.
This gives the result you expect
const response = [
{ Kom: 'abc', NumList: [{ Number: "cde"}], SerList: [{ Ser: "cdef" }] },
{ Kom: 'dfr', NumList: [{ Number: "dsf"}], SerList: [{ Ser: "sgsd"}] },
{ Kom: 'fgr', NumList: [{ Number: "zizu"}], SerList: [{ Ser: "hkl"}] }
];
let lastId = 1; // index var to increment
const result = response.map((item) => ({
KomRes: item.Kom,
id: lastId++,
levels: [
...item.NumList.map((item) => ({
id: lastId++,
KomRes: item.Number,
})
),
...item.SerList.map((item) => ({
id: lastId++,
KomRes: "Serial: " + item.Ser,
})
),
]
})
);
console.log(result)
I have a below JSON,
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
And am trying to add new data inside the nested array i.e., "vpainfo". I have tried using the below code and able to adding the new values inside "vpainfo".
var newdata = {"vpa":"first#bda","mccCode":"1111"};
var newObj =
Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>(todoInfo.accountNo=="50190000")?[
...todoInfo.vpainfo,
newdata
]: todoInfo)
});
And the resulted object is,
{"todos":[[{"vpa":"log#bda","mccCode":"0000"},{"vpa":"first#bda","mccCode":"1111"}]]}
But few of the key and values(accountNo and name) are getting missed, how do we get the full object with the latest updated values?
You only return the array, not the actual object, hence the error.
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
const newdata = {"vpa":"first#bda","mccCode":"1111"};
const newObj = Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>{
if(todoInfo.accountNo=="50190000"){
return {
...todoInfo,
vpainfo: [...todoInfo.vpainfo, newdata]
}
}
return todoInfo
})
});
console.log(newObj)
All those spread operators seem a little excessive...
If all you wanna do is add newdata to that existing array, then do that:
var original = {
"todos": [{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [{
"vpa": "log#bda",
"mccCode": "0000"
}]
}]
};
const newdata = {
"vpa": "first#bda",
"mccCode": "1111"
};
// Find the correct account.
const account = original.todos.filter(t => t.accountNo === '50190000')[0];
if (account) {
account.vpainfo.push(newdata);
}
console.log(original);
I tried to edit object in list with this variant
const { bins: data } = await client.get(key); // { array: [{ variable: 1 }, { variable: 2 }] }
const { array } = await client.operate(key, [Aerospike.maps.put('array', 3).withContext(ctx => ctx.addListIndex(1).addMapKey('variable'))]); // want to edit second object in array, but i get an error 'Operations array invalid'
Can i do it normally or only way to do it is just remove object by index and insert new one?
Yes, you can use Aerospike's Map operations to update the nested map value in place!
There are two problems with your operate command: The maps.put operation takes 3 parameters: The bin name (array in your case), the map key (variable) and the new value (3). And the context for this operation is just the 2nd list object - no need to add the map key as a context as well.
Here is a full, working example:
// nested-cdt-ops.js
const as = require('aerospike')
as.connect().then(async (client) => {
const key = new as.Key('test', 'test', 'nested')
{
const bins = { array: [{ variable: 1 }, { variable: 2 }] }
await client.put(key, bins)
console.log('BEFORE:', bins)
}
const operations = [
as.maps.put('array', 'variable', 3).withContext(
(ctx) => ctx.addListIndex(1)
)
]
await client.operate(key, operations)
{
const { bins } = await client.get(key)
console.log('AFTER:', bins)
}
client.close()
}).catch((error) => {
if (error.client) error.client.close()
console.error(error)
})
It outputs:
$ node nested-cdt-ops.js
BEFORE: { array: [ { variable: 1 }, { variable: 2 } ] }
AFTER: { array: [ { variable: 1 }, { variable: 3 } ] }
i'm having trouble turning a flat array to a multi nested array
[{
code: "1",
text: "FatturaElettronicaHeader",
},
{
code: "1.1",
text: "DatiTrasmissione",
},
{
code: "1.1.5",
text: "ContattiTrasmittente",
},
{
code: "1.1.5.1",
text: "Telefono",
},
{
code: "1.1.5.2",
text: "Email",
},
{
code: "1.2",
text: "CedentePrestatore",
}
]
i want it so that if an array elements code includes the code of another array element, it should be a child of that element. So 1.1 and 1.2 are both children of 1. then 1.1.5 is child of 1.1 only. there should only be one of each object in the new array
You can create nested tree structure using forEach loop to iterate through array and then for each object you can use split to get path array and reduce method to create nested structure based on the path array.
const data = [{"code":"1","text":"FatturaElettronicaHeader"},{"code":"1.1","text":"DatiTrasmissione"},{"code":"1.1.5","text":"ContattiTrasmittente"},{"code":"1.1.5.1","text":"Telefono"},{"code":"1.1.5.2","text":"Email"},{"code":"1.2","text":"CedentePrestatore"}];
const result = [], level = {result}
data.forEach(e => {
e.code.split('.').reduce((r, k) => {
if(!r[k]) {
r[k] = {result: []}
r.result.push({...e, children: r[k].result})
}
return r[k];
}, level)
})
console.log(result);
You can also use two reduce methods instead of forEach loop to get the same result.
const data = [{"code":"1","text":"FatturaElettronicaHeader"},{"code":"1.1","text":"DatiTrasmissione"},{"code":"1.1.5","text":"ContattiTrasmittente"},{"code":"1.1.5.1","text":"Telefono"},{"code":"1.1.5.2","text":"Email"},{"code":"1.2","text":"CedentePrestatore"}];
const result = data.reduce((level, {code, ...rest}) => {
return code.split('.').reduce((r, k) => {
if(!r[k]) {
const children = [];
r[k] = {result: children}
r.result.push({code, ...rest, children})
}
return r[k]
}, level), level
}, {result: []}).result
console.log(result);
Javascript:
$(document).ready(function() {
const ores = "../js/json/oreList.json";
const priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray = [];
let priceArray = [];
let total = 0;
// Retrieve list of ores
function getOres() {
$.getJSON(ores, function(ores) {
ores.forEach(function(ore) {
total++;
if (total === 48) {
getPrices();
}
oreArray.push(ore);
});
});
}
// Retrieve all items & prices via API
function getPrices() {
$.getJSON(priceURL, function(prices) {
prices.forEach(function(data) {
priceArray.push(data);
console.log(data);
});
});
}
getOres();
});
The first function creates an internal array from my .JSON file and the second function creates an internal array from the URL.
In the first array oreArray, an object looks like this:
{ id: 1234, name: "Title" }
In the second array priceArray, an object looks like this:
{ type_id: 1234, average_price: 56.34 }
My oreArray has 48 objects and unfortunately the priceArray has about 11,000 objects. I need to create a new array by comparing the two arrays and building new objects, where the ID's match. So for example objects in newArray would look like:
{ id: 1234, name: "Title", average_price: 56.34 }
Basically I'm having trouble figuring out the logic for:
For each object in oreArray, find the object with the same ID value in priceArray and append the new array with a new object using values from both arrays.
I would do it this way:
const ores = "../js/json/oreList.json",
priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray,
priceArray,
joinedArray = [];
function getOres() {
$.getJSON(ores, function(ores) {
oreArray = ores;
getPrices();
});
}
function getPrices() {
$.getJSON(priceURL, function(prices) {
priceArray = prices;
joinPrices();
});
}
function joinPrices() {
oreArray.forEach(function(ore) {
var matchingPrice = getMatchingPrice(ore);
if(matchingPrice !== false) {
joinedArray.push({
id: ore.id,
name: ore.name,
average_price: matchingPrice.average_price
});
}
});
}
function getMatchingPrice(ore) {
for(var i=0; i<priceArray.length; i++) {
if(priceArray[i].type_id === ore.id) {
return priceArray[i];
}
}
return false;
}
getOres();
I think that a good way to approach this problem is by changing the data structure of the average prices a little bit.
Instead of having them in an array, where each item has type_id and average_price field, you might want to consider using an object to store them, where the key is the type_id and the value is the average_price.
To be more concrete, you can replace:
prices.forEach(function(data) {
priceArray.push(data);
});
With:
const pricesMap = {};
prices.forEach(price => {
pricesMap[price.type_id] = price.average_price
});
And when looping on the oreArray, you can access each product's average_price by simply referring to pricesMap[ore.id]
You can check out this JSBin: http://jsbin.com/fogayaqexe/edit?js,console
You can use reduce to loop over each oreArr item and collect the data you need in the accumulator:
var oreArr=[
{ id: 1234, name: "Title" },
{ id: 2234, name: "2Title" },
]
var priceArr= [
{ type_id: 1234, average_price: 56.34 },
{ type_id: 2234, average_price: 256.34 },
{ type_id: 3234, average_price: 56.34 },
{ type_id: 4234, average_price: 56.34 },
]
var resArr = oreArr.reduce((ac,x) => {
var priceMatch = priceArr.find( z => z.type_id === x.id )
if(! priceMatch)
return ac //bail out if no priceMatch found
var res = Object.assign({}, x, priceMatch)
ac.push(res)
return ac
},[])
console.log(resArr)
other methods used:
arrayFind to check intersection
Object.assign to create the merged object to populate the accumulator
I suggest you to change your small json as object
eg : '{"1234":{"id": 1234, "name": "Title" }}';
var json = '{"1234":{"id": 1234, "name": "Title" }}';
oreArray = JSON.parse(json);
alert(oreArray['1234'].name); // oreArray[priceArraySingle.id].name
we can easily match priceArray id with oreArray.