I want to build an new JSON from existing one. The source has sections and rubrics that I no longer need for a listing. The new object called 'items' should have an array of the items.
The final JSON should be sorted by attribute 'name' and look like
{
"items": [
{
"id": 10000006,
"name": "Boah"
},
{
"id": 10000013,
"name": "Gut"
},
{
"id": 10000003,
"name": "Ipsum"
},
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000002,
"name": "Stet"
}
]
}
For building the new JSON I get this source:
{
"sections": [
{
"name": "FooBar",
"rubrics": [
{
"name": "Foo",
"items": [
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000002,
"name": "Stet"
},
{
"id": 10000003,
"name": "Ipsum"
}
]
},
{
"name": "Bar",
"items": [
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000006,
"name": "Boah"
}
]
}
]
},
{
"name": "BlahBloob",
"rubrics": [
{
"name": "Bla",
"items": [
{
"id": 10000013,
"name": "Gut"
}
]
},
{
"name": "Bloob",
"items": [
{
"id": 10000014,
"name": "Name"
},
{
"id": 10000015,
"name": "Lorem"
}
]
}
]
}
]
}
What do you think? How can I do this with plain JavaScript or maybe TypeScript?
Thanks for reading and have time for my question. And thanks for reply in advance.
Here you go. You just need to iterate over each rubric of each section of your source to get the items. At the end, sort your list of items by items, and you're done.
This example uses ES6 syntax, but it's easy to convert it to ES5 if needed.
function extractItems(source) {
const items = [];
for (const section of source.sections) {
for (const rubric of section.rubrics) {
items.push(...rubric.items);
}
}
items.sort((a, b) => a.name.localeCompare(b.name));
return { items };
}
A more functional approach use map and reduce to pick the rubrics and merge them.
data.sections
.map(section => section.rubrics) // get rubrics
.reduce((a, b) => a.concat(b)) // merge rubrics
.map(rubric => rubric.items) // get items from each rubric
.reduce((a, b) => a.concat(b)) // merge items
.sort((a, b) => a.name.localeCompare(b.name)); // sort
function(oldObj) {
var newObj = {
"items": []
};
oldObj.sections.forEach(function(section) {
section.rubrics.forEach(function(rubric) {
rubric.items.forEach(function(item) {
newObj.items.push(item);
});
});
});
newObj.items = newObj.items.sort(function(a, b) {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return newObj;
}
And simply use JSON.parse() and JSON.stringify() to convert JSON to and from objects.
It might help you
var data ={
"sections": [
{
"name": "FooBar",
"rubrics": [{"name": "Foo", "items": [{"id": 10000001,"name": "Lorem"}, {"id": 10000002,"name": "Stet"}, {"id": 10000003,"name": "Ipsum"}]
}, {
"name": "Bar",
"items": [{
"id": 10000004,
"name": "Name"
}, {
"id": 10000005,
"name": "Lorum"
}, {
"id": 10000006,
"name": "Boah"
}]
}]
}, {
"name": "BlahBloob",
"rubrics": [{
"name": "Bla",
"items": [{
"id": 10000013,
"name": "Gut"
}]
}, {
"name": "Bloob",
"items": [{
"id": 10000014,
"name": "Name"
}, {
"id": 10000015,
"name": "Lorem"
}]
}]
}]
};
var itemObj = {};
var itemArr = [];
var sections = data.sections;
for(var i=0;i<sections.length;i++)
{
for(var j=0;j<sections[i].rubrics.length;j++){
for(var k=0;k<sections[i].rubrics[j].items.length;k++){
var itemObj;
itemObj['id'] = sections[i].rubrics[j].items[k].id;
itemObj['name'] = sections[i].rubrics[j].items[k].name;
itemArr.push(itemObj);
}
}
}
var finalObj = {"items":itemArr};
console.log(finalObj);
JSFiddle
Related
I have a nested array like below. There are about 100 de objects in the array. The de objects also have deg[0] array but most likely I will only have the first index. Now the trick is that the de are subset of deg. Which means each deg can have say 10 de. How can I retrieve the deg and there associated de and map it into a new array like:
newArray = [
deg1: [
{de1},
{de2}
],
deg2: [
{de1},
{de2}
]
]
Here is my nested array. I posted four but the list is over a 100.
{
"name": "Report",
"id": "2YYUEZ6I1r9",
"dse1": [
{
"de1": {
"name": "Number",
"id": "HjMOngg3kuy",
"de1-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "TB",
"id": "2XJB1JO9qX8"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de1": {
"name": "Number of",
"id": "a3dtGETTawy",
"de1av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Tertiary",
"id": "w99RWzXHgtw"
}
]
}
}
]
}
Group array of objects by property (this time a property to be matched by a reg exp) using Array.reduce.
Update: Ignoring missing keys.
var input={name:"Report",id:"2YYUEZ6I1r9",dse1:[{de1:{name:"Number",id:"HjMOngg3kuy","de1-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"TB",id:"2XJB1JO9qX8"}]}},{de2:{name:"Number of",id:"a3dtGETTawy","de2-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de1:{name:"Number of",id:"a3dtGETTawy",de1av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de2:{name:"Number of",id:"a3dtGETTawy",de2av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Tertiary",id:"w99RWzXHgtw"}]}}]}
var reg = new RegExp("^de[0-9]+$");
var reg2 = new RegExp("^deg[0-9]+$");
let obj = input['dse1'].reduce(function(agg, item) {
// do your group by logic below this line
var key = Object.keys(item).find(function(key) {
return key.match(reg) ? key : null;
})
if (key) {
var key2 = Object.keys(item[key]).find(function(key) {
return key.match(reg2) ? key : null;
})
agg[key] = agg[key] || [];
if (key2) {
var to_push = {}
to_push[key2] = item[key][key2]
agg[key].push(to_push)
}
}
// do your group by logic above this line
return agg
}, {});
console.log(obj)
.as-console-wrapper {
max-height: 100% !important;
}
I need inner join with two array in javascript like this:
array1 =
[
{
"id": 1,
"name": "Tufan"
},
{
"id": 2,
"name": "Batuhan"
},
{
"id": 3,
"name": "Hasan"
}
]
array2 =
[
{
"name": "yyy",
"externalid": "1",
"value": "Asd"
},
{
"name": "aaaa"
"externalid": "2",
"value": "ttt"
}
]
expectedArray =
[
{
"id": 1,
"name": "Tufan",
"externalid": "1",
"value": "Asd"
},
{
"id": 2,
"name": "Batuhan",
"externalid": "2",
"value": "ttt"
}
]
rules:
on: array2.externalid = array1.id
select: array1.id, array1.name, array2.externalid, array2.value
My approach:
array1.filter(e => array2.some(f => f.externalid == e.id));
// I need help for continue
How can I make this?
Doesn't matter information: I use ES5 and pure javascript
You can do it like this:
const res = array2.map((item) => {
const related = array1.find((el) => el.id == item.externalid);
return { ...item, ...related };
});
Using a map to loop over the array2 and a find to get the array1 relative.
I need reorganize and array of linked objects by id to only one tree object. The depth level is unknown, so that I think that it should be done recursively. What is the most efficient way?
I have the next array of objects:
const arrObj = [
{
"id": 1,
"children": [
{
"id": 2
},
{
"id": 3
}
]
},
{
"id": 2,
"children": [
{
"id": 4
},
{
"id": 5
}
]
},
{
"id": 3,
"children": [
{
"id": 6
}
]
},
{
"id": 4
}
]
I want restructure for have a only one object like a tree:
const treeObj = {
"id": 1,
"children": [
{
"id": 2,
"children": [
{
"id": 4
},
{
"id": 5
}
]
},
{
"id": 3,
"children": [
{
"id": 6
}
]
}
]
}
Each object has other many properties.
You can use a recursive mapping function over all the children.
const arrObj = [ { "id": 1, "children": [ { "id": 2 }, { "id": 3 } ] }, { "id": 2, "children": [ { "id": 4 }, { "id": 5 } ] }, { "id": 3, "children": [ { "id": 6 } ] }, { "id": 4 } ];
const res = arrObj[0];//assuming the first element is the root
res.children = res.children.map(function getChildren(obj){
const child = arrObj.find(x => x.id === obj.id);
if(child?.children) child.children = child.children.map(getChildren);
return child || obj;
});
console.log(res);
Can't use javascript filter in multi-dimensional object.
var object = [{
"id": "1",
"name": "General",
"cards": [{
"id": "1",
"name": "shawn"
}, {
"id": "2",
"name": "neo"
}]
}, {
"id": "2",
"name": "CEO",
"cards": [{
"id": "1",
"name": "Raman"
}, {
"id": "2",
"name": "Sheena"
}]
}]
function searchFor(item) {
return item.cards.filter(
(card) => {
return card.name.indexOf("Raman") !== -1;
}
);
}
var filtered = object.filter(searchFor);
console.log(filtered);
This is how I am trying, inside the searchFor card.name I am getting the correct card name but filtering is returning all the cards.Its not filtering.
Could any help me with this.
An empty array isn't considered falsey in Javascript. So instead of returning the result of filtering the cards array, test its length.
var object = [{
"id": "1",
"name": "General",
"cards": [{
"id": "1",
"name": "shawn"
}, {
"id": "2",
"name": "neo"
}]
}, {
"id": "2",
"name": "CEO",
"cards": [{
"id": "1",
"name": "Raman"
}, {
"id": "2",
"name": "Sheena"
}]
}]
function searchFor(item) {
return item.cards.filter(
(card) => {
return card.name.indexOf("Raman") !== -1;
}
).length != 0;
}
var filtered = object.filter(searchFor);
console.log(filtered);
You were returning the filtered array, which would produce a TRUE result whenever cards existed. So you can just turn that into a boolean, by saying when the item.cards.filter(...).length > 0.
var object = [{
"id": "1",
"name": "General",
"cards": [{
"id": "1",
"name": "shawn"
}, {
"id": "2",
"name": "neo"
}]
}, {
"id": "2",
"name": "CEO",
"cards": [{
"id": "1",
"name": "Raman"
}, {
"id": "2",
"name": "Sheena"
}]
}]
var searchFor = (card) => card.name.indexOf("Raman") > -1;
var filteredCards = object.reduce((cards, item) => cards.concat(item.cards.filter(searchFor)), []);
var filteredObj = object.map(i => {
i.cards = i.cards.filter(searchFor);
return i;
}).filter(i => i.cards.length)
console.log(filteredCards, filteredObj)
Updated
I updated the code snippet to produce either the cards which were found. I also provide a method for returning all objects which contain the needed cards, and filter out the other cards.
// HTML Part
<div class="filter-list">
<button class="filter" data-filter-key="all">all</button>
<button class="filter" data-filter-key="open">open</button>
<button class="filter" data-filter-key="done">done</button>
</div>
// CSS Part
.filter:hover,
.filter:focus,
[data-active-filter="all"] .filter[data-filter-key="all"],
[data-active-filter="done"] .filter[data-filter-key="done"],
[data-active-filter="open"] .filter[data-filter-key="open"] {
text-decoration: underline;
}
[data-active-filter="open"] [data-completed="true"],
[data-active-filter="done"] [data-completed="false"] {
display: none;
}
// Script Part
(function () {
const mainNode = document.querySelector("main");
const filters = document.querySelector(".filter-list");
for (const filter of filters.children) {
filter.addEventListener("click", () => {
mainNode.setAttribute(
"data-active-filter",
filter.getAttribute("data-filter-key")
);
});
}
mainNode.setAttribute("data-active-filter", "all");
})();
I need to create a function the would return the name of the car when given the id.
I have this data:
{
"cars": [
{
"id": "661",
"name": "ford"
},
{
"id": "657",
"name": "fiat",
},
{
"id": "654",
"name": "volvo",
},
{
"id": "653",
"name": "porche",
},
{
"id": "650",
"name": "mazda",
}
]
}
So I've done this:
function getCarNameFromId(id) {
theData = {
"cars": [
{
"id": "661",
"name": "ford"
},
{
"id": "657",
"name": "fiat",
},
{
"id": "654",
"name": "volvo",
},
{
"id": "653",
"name": "porche",
},
{
"id": "650",
"name": "mazda",
}
]
};
console.log(theData.name);
}
then call it:
function getCarNameFromId('650');
How do I finish this code so I can get the code to return me the name of the id specified?
JS solution
var findCar = function(id) {
var theData = {
"cars": [{
"id": "661",
"name": "ford"
},
{
"id": "657",
"name": "fiat",
},
{
"id": "654",
"name": "volvo",
},
{
"id": "653",
"name": "porche",
},
{
"id": "650",
"name": "mazda",
}
]
};
for (var i = 0; i < theData.cars.length; i++) {
var car = theData.cars[i];
if (car.id === id)
return car.name;
}
}
console.log(findCar("654"));
If you are using any mordenr browser you can use find method to find object from array
function getCarNameFromId(id) {
......
..........
.....
var obj = theData.cars.find( function(el) {
return el.id == id
})
if(obj){
return obj.name
} else {
return ''; // or just without any value.
}
}
if still want to support old browsers i would recommand to use lodash.js or underscore.js
cars.find(car => car.id === id).name
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions