Merging 2 arrays in JavaScript - javascript

I have 2 arrays and I would like to combine the two arrays which will result in the third array, like in the second image. How can I do that?
const mapper = {
characters: {
'onepiece': {
'luffy': 'pirate king',
'sanji': 'cook'
},
'deathnote': {
'ryuk': 'shinigami',
'lee': 'weirdo :)'
}
},
animes: {
'onepiece': 'one piece',
'deathnote': 'death note'
}
}
I wanted to have a result like this:
'Luffy : Pirate King in One Piece',
'Sanji : Cook in One Piece',
'Ryuk : Shinigami in Death Note',
'Lee : Weirdo :) in Death Note'

Javascript implementation
const mapper = {
characters: {
'onepiece': {
'luffy': 'pirate king',
'sanji': 'cook',
},
'deathnote': {
'ryuk': 'shinigami',
'lee': 'weirdo :)',
},
},
animes: {
'onepiece': 'one piece',
'deathnote': 'death note',
},
};
const result = Object.assign({}, mapper.characters.onepiece, mapper.characters.deathnote);
console.log(result);

You can do nested a classic for / in loop for this.
const mapper = {
characters: {
'onepiece': {
'luffy': 'pirate king',
'sanji': 'cook'
},
'deathnote': {
'ryuk': 'shinigami',
'lee': 'weirdo :)'
}
},
animes: {
'onepiece': 'one piece',
'deathnote': 'death note'
}
};
let result = [];
for (var key in mapper.characters) {
for (var key2 in mapper.characters[key]) {
result.push(jsUcfirst(key2) + " : " + jsUcfirst(mapper.characters[key][key2]) + " in " + jsUcfirst(mapper.animes[key]));
}
}
//Capitalize first letter of each word on a string
function jsUcfirst(string) {
let arr = [];
string = string.split(" ");
for (var key in string) arr.push(string[key].charAt(0).toUpperCase() + string[key].slice(1));
return arr.join(" ");
}
console.log(result);

Related

Updating JSON structure based on id

I was trying to update the town name in the below-given JSON structure.
"City":[
{
"Name":"Delhi",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd",
"Towns":[
{
"Name":"MG Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
},
{
"Name":"DLF Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
}
]
},
{
"Name":"Pune",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax",
"Towns":[
{
"Name":"Hadapsar",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1x4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax"
},
{
"Name":"Magarpatta",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1f4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bax"
}
]
}
]
I wanted to change the town name from "Hapdasar" to "Viman Nagar" if my cid matches that of Hadapsar Town
Output which I wanted was:
"City":[
{
"Name":"Delhi",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd",
"Towns":[
{
"Name":"MG Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
},
{
"Name":"DLF Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
}
]
},
{
"Name":"Pune",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax",
"Towns":[
{
"Name":"Viman Nagar",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1x4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax"
},
{
"Name":"Magarpatta",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1f4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bax"
}
]
}
]
I was using js map to iterate but was confused about how to replicate the exact structure.
Well, map alone is not enough to solve your problem, since you have two nested arrays. Maybe you can consider the possibility to use maptwice?
For example:
var cid = "c5d58bef-f1c2-4b7c-a6d7-f64df12321ax";
var newName = "Viman Nagar";
City = City.map(function(city) {
city.towns = city.towns.map(function(town) {
if (town.cid === cid)
town.name = newName;
return town;
});
return city;
});
Atribute your object for
let cities = [{
"Name": "Delhi"
...
}]
and then you can map over it
let result = cities.map(city => city.Towns.map(town => {
if (town.Name === "Hadapsar") {
return {
...town,
Name: "Viman Nagar"
}
} else return town
}))
Use Array#map as follows:
Iterate over cities
In every iteration, iterate over Towns. If current town's cid is equal to the one to change, update its Name
const changeTownName = (cities = [], cid, name) =>
cities.map(({ Towns = [], ...props }) => ({
...props,
Towns: Towns.map(town => town.cid === cid
? { ...town, Name: name }
: { ...town }
)
}));
const cities = [
{ Name: 'Delhi', id: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321bd', Towns: [ { Name: "MG Colony", conditionId: '60d1f5eb-0222-4a84-879b-6699b0cfc1a4', cid: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321bd' }, { Name: "DLF Colony", conditionId: '60d1f5eb-0222-4a84-879b-7749b0cfc1a4', cid: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321bd' } ] },
{ Name: 'Pune', id: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321ax', Towns: [ { Name: "Hadapsar", conditionId: '60d1f5eb-0222-4a84-879b-6699b0cfc1x4', cid: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321ax' }, { Name: "Magarpatta", conditionId: '60d1f5eb-0222-4a84-879b-7749b0cfc1f4', cid: 'c5d58bef-f1c2-4b7c-a6d7-f64df12321bax' } ] }
];
console.log( changeTownName(cities, 'c5d58bef-f1c2-4b7c-a6d7-f64df12321ax', 'Viman Nagar') );
If you consider city as cities this code can help you;
cities.forEach(city => {
city.Towns = city.Towns.map(el => {
if (el.Name === 'Hapdasar') {
el.Name = 'Viman Nagar';
}
return el;
})
});
You'll need to loop for each city in your array, and each town in the city. If the cid matches the town's cid, then change it;
const myNewTownName = "Viman Nagar";
const cid = "c5d58bef-f1c2-4b7c-a6d7-f64df12321ax";
for(let i = 0; i < myObj.City.length; i++){
const city = myObj.City[i];
for(let j = 0; j < city.Towns.length; j++){
const town = city.Towns[j];
if(cid === town.cid){
town.Name = myNewTownName;
}
city.town[j] = town;//Updates city with the updated town
}
myObj.City[i] = city; //Updates myObj with the updated city
}
The result can also be obtained using nested .forEach loops to parsing through the outer and inner arrays, with an if block to examine the cid for the target town.
const data = {
"City":[
{
"Name":"Delhi",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd",
"Towns":[
{
"Name":"MG Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
},
{
"Name":"DLF Colony",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1a4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bd"
}
]
},
{
"Name":"Pune",
"id":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax",
"Towns":[
{
"Name":"Hadapsar",
"conditionId":"60d1f5eb-0222-4a84-879b-6699b0cfc1x4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321ax"
},
{
"Name":"Magarpatta",
"conditionId":"60d1f5eb-0222-4a84-879b-7749b0cfc1f4",
"cid":"c5d58bef-f1c2-4b7c-a6d7-f64df12321bax"
}
]
}
]
} // end data;
const targetCid = "c5d58bef-f1c2-4b7c-a6d7-f64df12321ax"; // cid for Hadapsar;
const objArray = data.City;
objArray.forEach(element => {
element.Towns.forEach(element => {
if (element.cid == targetCid) {
element.Name = "Viman Nagar";
} // end if;
}); // next object in Towns array;
}); // next object in objArray;
document.getElementById('output').textContent = JSON.stringify(data, undefined, 2);
#output {
white-space: pre;
}
<pre id="output"></pre>

Array of objects how do i check for deeply nested text string duplicates & remove from array?

I have an array of objects
Deep inside those objects is a text string
I want to check if other objects in the same array have the same text string / are duplicates.
Then i need a new array with those duplicates removed.
I thought this would be quite simple but it's been testing my intellect for two days now.
const arr = [
{..obj 1}
{..obj 2}
{..obj 3}
{
id: 4,
uid: 24872-2847-249249892842,
tags: ['some', 'stuff'],
type: "blogpage",
href: "https://link-to-stuff",
first_publication_date: "2020-02-12T16:05:04+0000",
last_publication_date: "2020-02-18T21:52:06+0000",
data: {
...some stuff
heading: [
{ type: "heading1", text: "Here Is My Text I Need To Check Duplicates
Of"}
]
}
}
{..obj 5}
{..obj 6}
{..obj 7}
{..obj 8}
{..obj 9}
{..obj 10}
]
I figured something like:
filterOutDuplicates = (blogIndexContent) => {
let arr = blogIndexContent.pages;
let results = [];
arr.map(each => {
if (!results || !results.length) {
results.push(each);
} else {
for (let i = 0; i < results.length; i++) {
const headline = results[i].data.heading[0].text;
if (headline === each.data.heading[0].text) {
return;
} else {
return results.push(each);
}
}
}
})
console.log('Results :', results); // <-- this just gives me the same 9 blog stories again, no duplicates removed.
}
What am i doing wrong guys?
If you dont mind using lodash, it could be easily solved using _.uniqBy
const withoutDups = _.uniqBy(arr, 'data.heading[0].text')
Try this
const arr = [
{
id: 4,
data: {
heading: [
{
type: "heading1",
text: "Here Is My Text I Need To Check Duplicates Of"
}
]
}
},
{
id: 5,
data: {
heading: [
{
type: "heading1",
text: "Here Is My Text I Need To Check Duplicates Of"
}
]
}
},
{
id: 6,
data: {
heading: [
{
type: "heading1",
text: "Not Duplicates"
}
]
}
}
];
const withoutDuplicates = arr.reduce(
(prev, curr) =>
prev
.map(d => d["data"]["heading"][0]["text"])
.includes(curr["data"]["heading"][0]["text"])
? [curr]
: [...prev, curr],
[]
);
console.log(withoutDuplicates);
Slight changes to your code
1) remove using map, have loop over array.
2) Build the uniq object with keys. (Here headline is what we want)
3) Add to results array only when key is not in uniq
let arr = blogIndexContent.pages;
let results = [];
const uniq = {};
for (let i = 0; i < arr.length; i++) {
const headline = arr[i].data.heading[0].text;
if (!(headline in uniq)) {
results.push(each);
uniq[each] = 1;
}
}
console.log("Results :", results);
This should work for you:
filterOutDuplicates = blogIndexContent => {
let arr = blogIndexContent.pages
const result = []
arr.forEach(each => {
if (result.length === 0) {
result.push(each)
}
else {
const headline = each.data.heading[0].text
let found = false
for (let i = 0; i < result.length; i++) {
if (result[i].data.heading[0].text === headline) {
found = true
break
}
}
if (!found) {
result.push(each)
}
}
})
console.log('Results :', results)
}

With an identifier traverse through a JSON object and get a specific value with the identifier

Traverse through a JSON object which has nested arrays objects inside it .
The label value is provided which is the identifier with which need to return the associated level metrics value . If the label is found in the 2nd level find the metrics at the second level and it should be returned
I couldn't get the logic on how to traverse through an object and return the specific value
function getMetrics(arr, label) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].label === label) {
return arr[i].metricsValue;
} else if (arr[i].children) {
return getMetrics(arr[i].children, label);
}
}
return "Not found";
}
const selectedMetrics = getMetrics(dataObj.series, '1');
Consider the JSON object with children specifies the sub level of the current level .
const dataObj = {
series: [
{
label: "A",
metricsValue: "ma",
children: [
{
label: "A-B",
value: 6,
metricsValue: "ma-mb"
},
{
label: "A-B-C",
metricsValue: "ma-mb-mc",
children: [
{
label : "A-B-C-D",
value: 6,
metricsValue: "ma-mb-mc-md"
}
]
}
]
},
{
label: "1",
metricsValue: "m1",
}
]
};
Expected Result :
When the input is "1", it should return
selectedMetrics= "m1"
Input : "A-B-C-D"
selectedMetrics= "ma-mb-mc-md"
You can perform a Depth first search (DFS) or Breadth first search (BFS) to find metricValues at any level.
Here I'm using DFS to find the required value. This works for data with any nested levels.
const dataObj = { series: [ { label: "A", metricsValue: "ma", children: [ { label: "A-B", value: 6, metricsValue: "ma-mb" }, { label: "A-B-C", metricsValue: "ma-mb-mc", children: [ { label: "A-B-C-D", value: 6, metricsValue: "ma-mb-mc-md" } ] } ] }, { label: "1", metricsValue: "m1"} ] };
function getMetrics(arr, label) {
var result;
for (let i = 0; i < arr.length; i++) {
if (arr[i].label === label) {
return arr[i].metricsValue;
} else if (arr[i].children) {
result = getMetrics(arr[i].children, label);
if (result) {
return result;
}
}
}
return null;
}
console.log("selectedMetrics for 'A' = " + getMetrics(dataObj.series, 'A'));
console.log("selectedMetrics for 'A-B' = " + getMetrics(dataObj.series, 'A-B'));
console.log("selectedMetrics for 'A-B-C' = " + getMetrics(dataObj.series, 'A-B-C'));
console.log("selectedMetrics for 'A-B-C-D' = " + getMetrics(dataObj.series, 'A-B-C-D'));
console.log("selectedMetrics for '1' = " + getMetrics(dataObj.series, '1'));
Your'e passing in the value, so use it instead of the string & you're not accessing the children nodes.
for(var i=0; i< arr.length;i++){
const x = arr[i];
if (x.children.label === value) {
console.log(x.metricValue)
}else{
x.forEach(element => {
if (element.children.label === value) {
console.log(element.metricValue)
}else{
element.forEach(secondEl =>{
if (secondEl.children.label === value) {
console.log(secondEl.metricValue)
}
})
}
});
}
}
You can create a more elegant way of iterating around the children nodes but that may help you out

How to convert array of objects to serialised?

I have an array of object
const parameters = [
{token: '78fe6df3f'},
{id: '12345'},
{ price: '0 - 9,000,000' },
{ 'area[]': 'Applehead Island' },
{ 'waterfront_type[]': 'Open Water' },
{ property_type_single: 'Single Family/Site Built' },
{ bedrooms: '0 - 5' },
{ baths: '0 - 5' },
{ sqft: '0 - 7500' }
];
I want this object to be turned to like below
https://www.example.com/properties.php?token=78fe6df3f&id=12345&price=$0%20-%20$3,480,000&area[]=Applehead%20Island&waterfront_type[]=Open%20Water&property_type_single=Single%20Family/Site%20Built&bedrooms=0%20-%205&baths=0%20-%205&sqft=0%20-%207500
Please help on how to get this?
Assuming that this is JavaScript, you can use the encodeURIComponent() function to URL-encode all of your key-value pairs as you have shown. Simply iterate over the array and concatenate the URL-encoded values:
const parameters = [
{ token: '78fe6df3f'},
{ id: '12345'},
{ price: '0 - 9,000,000' },
{ 'area[]': 'Applehead Island' },
{ 'waterfront_type[]': 'Open Water' },
{ property_type_single: 'Single Family/Site Built' },
{ bedrooms: '0 - 5' },
{ baths: '0 - 5' },
{ sqft: '0 - 7500' }
];
let uri = "https://example.org/properties.php?";
let firstSegment = true;
for(const param of parameters) {
if(!firstSegment) {
uri += "&";
firstSegment = false;
}
// find out the name of this object's property
const paramName = Object.keys(param)[0];
uri += paramName + "=" + encodeURIComponent(param[paramName]);
}
console.log(uri);
This can be written more concisely using map() and join():
const parameters = [
{ token: '78fe6df3f'},
{ id: '12345'},
{ price: '0 - 9,000,000' },
{ 'area[]': 'Applehead Island' },
{ 'waterfront_type[]': 'Open Water' },
{ property_type_single: 'Single Family/Site Built' },
{ bedrooms: '0 - 5' },
{ baths: '0 - 5' },
{ sqft: '0 - 7500' }
];
let uri = "https://example.org/properties.php?" +
parameters
.map(
param => {
const name = Object.keys(param)[0];
return name + "=" + encodeURIComponent(param[name]);
})
.join("&");
console.log(uri);
You could merge all objects into one, go over its properties and merge it to one string:
const result = encodeURIComponent(Object.entries(Object.assign({}, ...parameters)).map(([key, value]) => key + "=" + value).join("&"));
Step by step:
[{ k: v }, { k2, v2 }]
1) Object.assign({}, ...parameters)
{ k: v, k2: v2 }
2) Object.entries(...)
[[k, v], [k2, v2]]
3) .map(([key, value]) => key + "=" + value)
["k=v", "k2=v2"]
4) .join("&")
"k=v&k2=v2"
My goal in stack overflow is to explain concepts in a very simplified manner .I have commented in the code , so you will understand every step .
The ${} are ES6 concepts , if you have never seen them , refer to this article
Thanks for challenging me.
So here is my solved code , short and easy .
var parameters = [
{token: '78fe6df3f'},
{id: '12345'},
{ price: '0 - 9,000,000' },
{ 'area[]': 'Applehead Island' },
{ 'waterfront_type[]': 'Open Water' },
{ property_type_single: 'Single Family/Site Built' },
{ bedrooms: '0 - 5' },
{ baths: '0 - 5' },
{ sqft: '0 - 7500' }
];
//we initialize an empty variable
var serializedString = '';
//.map() This loop will loop through the array to pick each object
parameters.map((i)=>{
//for-in This loop goes through the key-value inside of each object
for(var key in i){
//here we are assigning the stringed values into the variable we declared earlier on
serializedString +=`${key}=${i[key]}&`;
}
});
//after all this is done , we convert our string into a URL friendly string
var ourURL_friendlyResult = encodeURIComponent(serializedString);
//we console it out
console.log(`https://example.org/properties.php?${ourURL_friendlyResult}`);

Combining a collection of objects based on multiple properties

Is there a Javascipt or a Lodash method to combine this collection of objects:
[
{
typeId: 'random1'
catId: 'random2'
val: '2'
},
{
typeId: 'random1'
catId: 'random2'
val: '3'
},
{
typeId: 'random1'
catId: 'random4'
val: '1'
}
]
into this one, with each object with unique typeId-catId pair and the numerical value to be summed up:
[
{
typeId: 'random1'
catId: 'random2'
val: '5'
},
{
typeId: 'random1'
catId: 'random4'
val: '1'
}
]
First create an object which keeps track of total val of similar objects and then process them into final output format. Something like this:
var data = [
{
typeId: 'random1',
catId: 'random2',
val: '2'
},
{
typeId: 'random1',
catId: 'random2',
val: '3'
},
{
typeId: 'random1',
catId: 'random4',
val: '1'
}
];
var groups = data.reduce(function(acc, obj) {
acc[obj.typeId+'_'+obj.catId] = acc[obj.typeId+'_'+obj.catId] || 0;
acc[obj.typeId+'_'+obj.catId] += +obj.val;
return acc;
}, {});
var result = Object.keys(groups).map(function(key) {
return {
typeId: key.split('_')[0],
catId: key.split('_')[1],
val : groups[key]
}
});
console.log(result);
You can use forEach() loop and thisArg param to group objects by typeId and catId properties.
var arr = [{"typeId":"random1","catId":"random2","val":"2"},{"typeId":"random1","catId":"random2","val":"3"},{"typeId":"random1","catId":"random4","val":"1"}]
var result = [];
arr.forEach(function(e) {
var key = e.typeId + '|' + e.catId
if(!this[key]) this[key] = e, result.push(this[key])
else this[key].val = +this[key].val + +e.val
}, {});
console.log(result)
You could use query-js(*) for this. The module hasn't been maintained for a while though. You would do somthing like this:
arr.groupBy(function(e){return e.typeId + e.catId;}).each(function(grp){
let first = grp.first();
return {
typeId : first.typeId,
catId : first.catId,
val : grp.sum(function(e){return 0 + e.val;})
};
});
It will first group the objects and then do the calculation on each group
(*) Be aware that I'm entirely biased and you can't take my words as a recommendation but only suggestion, since I'm the creator of query-js
What about this one ?
for (var i=0; i<array.length; i++) {
for (var j=i+1; j<array.length; j++) {
if (array[i].typeId == array[j].typeId && array[i].catId == array[j].catId) {
array[i].val = parseInt(array[i].val) + parseInt(array[j].val);
array.splice(j--, 1);
}
}
}

Categories