This question already has answers here:
How to find a node in a tree with JavaScript
(19 answers)
Closed 3 months ago.
I need to search the elements containing the searched text in a parent and child structure, similar to this:
[
{
"id": "1",
"name": "Apple",
"value": "1",
"children": [
{
"id": "4",
"name": "iPhone",
"value": "4",
}
]
},
{
"id": "2",
"name": "Samsung",
"value": "2",
"children": [
{
"id": "5",
"name": "Android",
"value": "5",
}
]
},
{
"id": "3",
"name": "AppleX",
"value": "3",
}
]
An example: the user searched for the string "Apple", he would need to filter all the elements of this structure that contain this string "Apple".
The search is always based on the object name.
It also gives nth level depth search result :
let arr = [
{
id: "1",
name: "Name 1",
value: "1",
children: [
{
id: "4",
name: "Name one",
value: "4",
children: [
{
id: "41",
name: "Name one",
value: "41",
},
],
},
],
},
{
id: "2",
name: "Name 2",
value: "2",
children: [
{
id: "5",
name: "Name 5 three one",
value: "5",
},
],
},
{
id: "3",
name: "Name 3",
value: "3",
},
];
let str = "one";
let stack = arr;
let result = [];
while (stack.length) {
let elem = stack.shift();
if (elem.children && elem.children.length > 0) {
stack.push(...elem.children);
}
//
let keys = Object.keys(elem).filter((v) => v != "children");
keys.map((m) => {
if (elem[m].includes(str)) {
delete elem["children"];
result.push(elem);
}
});
//
}
console.log(result);
Related
I need to find value of type2.id where id is 7 in the following object
[
{
"type1": {
"id": "1",
"value": "val1"
},
"type2": [
{
"id": "2",
"value": "val2"
}
]
},
{
"type1": null,
"type2": [
{
"id": "5",
"value": "val5"
}
]
},
{
"type1": {
"id": "3",
"value": "val3"
},
"type2": [
]
},
{
"type1": {
"id": "4",
"value": "val4"
},
"type2": [
{
"id": "7",
"value": "val7"
}
]
}
]
Please notice type1 is a simple object and type 2 is an array here, there can be empty array in type2 as well.
arr.find(({type2}) => type2[0]?.id === '7')?.type2[0].value
let value = null;
// First way using forEach
obj.forEach(item => {
if (item.type2 && item.type2.length > 0) {
item.type2.forEach(type2 => {
if (type2.id === '7') {
value = type2.value;
}
});
}
});
console.log("first way : ", value);
// Second way using map and filter
let type2Array = obj.map(obj => obj.type2).flat()
value = type2Array.filter(obj => obj.id === '7').at(0)?.value
console.log("second way : ", value);
<script>
const obj = [{
"type1": {
"id": "1",
"value": "val1"
},
"type2": [{
"id": "2",
"value": "val2"
}]
},
{
"type1": null,
"type2": [{
"id": "5",
"value": "val5"
}]
},
{
"type1": {
"id": "3",
"value": "val3"
},
"type2": [
]
},
{
"type1": {
"id": "4",
"value": "val4"
},
"type2": [{
"id": "7",
"value": "val7"
}]
}
];
</script>
Try this
const data = [
{
type1: {
id: "1",
value: "val1",
},
type2: [
{
id: "2",
value: "val2",
},
],
},
{
type1: null,
type2: [
{
id: "5",
value: "val5",
},
],
},
{
type1: {
id: "3",
value: "val3",
},
type2: [],
},
{
type1: {
id: "4",
value: "val4",
},
type2: [
{
id: "7",
value: "val7",
},
],
},
];
const result = data.find((object) => {
const { type2 } = object;
if (!type2) {
return false;
}
const [ firstFromType2 ] = type2;
if (!firstFromType2) {
return false;
}
return firstFromType2.id === '7';
});
console.log(result);
const data = [{"type1":{"id":"1","value":"val1"},"type2":[{"id":"2","value":"val2"}]},{"type1":null,"type2":[{"id":"5","value":"val5"}]},{"type1":{"id":"3","value":"val3"},"type2":[]},{"type1":{"id":"4","value":"val4"},"type2":[{"id":"7","value":"val7"}]}]
console.log(data.flatMap(i=>i.type2).find(({id})=>id==='7')?.value)
Assign the array to a const and make a nested map.
const foundObj = array.map(obj => obj.type2.map(type2obj => type2obj.id === '7')));
const value = foundObj.value
fiddle here: https://jsfiddle.net/
This is my json object:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
I want my output like this:
{
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"cats": [1,2] // this 1 and 2 is coming from categoriesservices array inside the category object i have id
}
How to do this using map function? I am new to javascript, which is good approach map or forloop?
See destructuring assignment, Array.prototype.map(), and JSON for more info.
// Input.
const input = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
// Categories => Objects to Cats => Ids.
const output = (input) => JSON.parse(JSON.stringify({
...input,
cats: input.categoryservices.map(({category: {id}}) => id),
categoryservices: undefined
}))
// Log.
console.log(output(input))
If you are not worried about original object immutability, then try this
obj['cats'] = obj['categoryservices'].map(cat => cat.category.id);
delete obj['categoryservices'];
console.log(obj);
I just use .map() on categoryservices array:
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map((element) =>
element.category.id);
delete output.categoryservices;
console.log(JSON.stringify(output));
use .map() , it return value as array ! You want to change is categoryservices key only ! So delete that after you get wanted value ..
var output = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
output.cats = output.categoryservices.map(i => i.category.id );
delete output.categoryservices;
console.log(output);
Try this working demo :
var jsonObj = {
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
};
var arr = jsonObj.categoryservices.map(item => item.category.id)
jsonObj.cats = arr;
delete jsonObj.categoryservices;
console.log(jsonObj);
Try this
var testData={
"id": 2,
"service": "mobile",
"min": "20",
"per": "10",
"tax": "1",
"categoryservices": [
{
"category": {
"id": 1,
"name": "laptop"
}
},
{
"category": {
"id": 2,
"name": "software"
}
}
]
}
testData.cats=[];
testData.categoryservices.forEach(function (item) {
testData.cats.push(item.category.id);
});
delete testData.categoryservices;
console.log(testData);
You can try using jquery each:
<div id="log"></div>
var conversation = {
'John': {
1: 'Test message 1',
2: 'Test message 2',
'Reply': {
3: 'Test message 3',
4: 'Test message 4'
}
},
'Jack': {
5: 'Test message 5',
6: 'Test message 6'
}
};
function iterate(obj) {
if (typeof obj === 'string') {
$('#log').append((obj + '<br/>'));
}
if (typeof obj === 'object') {
$.each(obj, function(key, value) {
iterate(value);
});
}
}
iterate(conversation);
I'm working with the following data structure:
"data": {
"products": [
[
{
"category": "A",
"items": [
{
"name": "Aloe",
"price": 10
},
{
"name": "Apples",
"price": 5
}
]
},
{
"category": "B",
"items": [
{
"name": "Bread",
"price": 5
}
]
}
],
[
{
"category": "C",
"items": [
{
"name": "Candy",
"price": 5
},
{
"name": "Crayon",
"price": 5
}
]
},
{
"category": "D",
"items": [
{
"name": "Dice",
"price": 5
},
{
"name": "Doll",
"price": 10
}
]
}
]
]
}
I'd like extract parts of it to flatten so the results is as follows:
[
{
"name": "Aloe",
"price": 10
},
{
"name": "Apples",
"price": 5
},
{
"name": "Bread",
"price": 5
},
{
"name": "Candy",
"price": 5
},
{
"name": "Crayon",
"price": 5
},
{
"name": "Dice",
"price": 5
},
{
"name": "Doll",
"price": 10
}
]
How can I accomplish this?
I have tried this:
for (var sets in data.products) {
for (var categories in sets) {
for (var items in categories) {
for (var item in items) {
// assemble new array
}
}
}
}
... but had problems looping through the children objects. I've found a couple other similar questions, but they seem to address simpler data structures, and flatten the entire object rather than parts of it.
Any pointers would be appreciated.
input.data.products. ....
maube Change in row 1 depend on your variable name
var result =[]
input.data.products.forEach(function (product){
product.forEach(function(productinfo){
productinfo.items.forEach(function (item){
result.push(item)
})
})
})
You will have to try something like this:
Logic:
Loop over data.products to get individual product details.
Sine details are also arrays, loop over them and return items from them.
The trick is, you will have to use Array.prototype.concat to merge arrays returned, to flatten them.
var data = {
"products": [
[{
"category": "A",
"items": [{
"name": "Aloe",
"price": 10
},
{
"name": "Apples",
"price": 5
}
]
},
{
"category": "B",
"items": [{
"name": "Bread",
"price": 5
}]
}
],
[{
"category": "C",
"items": [{
"name": "Candy",
"price": 5
},
{
"name": "Crayon",
"price": 5
}
]
},
{
"category": "D",
"items": [{
"name": "Dice",
"price": 5
},
{
"name": "Doll",
"price": 10
}
]
}
]
]
}
var result = [].concat.apply([], data.products.map(function(product){
return [].concat.apply([], product.map(function(p){
return p.items
}))
}))
console.log(result)
I have assigned your JSON object for data to a variable first. See the code below:
var pro={
"products": [
[
{
"category": "A",
"items": [
{
"name": "Aloe",
"price": 10
},
{
"name": "Apples",
"price": 5
}
]
},
{
"category": "B",
"items": [
{
"name": "Bread",
"price": 5
}
]
}
],
[
{
"category": "C",
"items": [
{
"name": "Candy",
"price": 5
},
{
"name": "Crayon",
"price": 5
}
]
},
{
"category": "D",
"items": [
{
"name": "Dice",
"price": 5
},
{
"name": "Doll",
"price": 10
}
]
}
]
]
}
var flatArray=[];
for(var i=0; i<pro.products.length; i++){
for(var j=0; j<pro.products[i].length;j++){
for(var k=0; k<pro.products[i][j].items.length;k++){
flatArray.push(pro.products[i][j].items[k]);
}
}
}
The flatArray will be your required flattened array of objects. Hope this is clear enough.
You can use array#reduce, array#forEach and array#concat.
var input = { data: { products: [[{ category: "A", items: [{ name: "Aloe", price: 10 }, { name: "Apples", price: 5 }] }, { category: "B", items: [{ name: "Bread", price: 5 }] }], [{ category: "C", items: [{ name: "Candy", price: 5 }, { name: "Crayon", price: 5 }] }, { category: "D", items: [{ name: "Dice", price: 5 }, { name: "Doll", price: 10 }] }]] } };
const result = input.data.products.reduce((res, arr) => {
arr.forEach( o => res = res.concat(o.items));
return res;
},[]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use a recursive approach by checking the items property or return the result of reduced properties. This approach works for any depth with an expected items property at the end.
function flat(object) {
return object.items || Object.keys(object).reduce(function (r, k) {
return r.concat(flat(object[k]));
}, []);
}
var object = { data: { products: [[{ category: "A", items: [{ name: "Aloe", price: 10 }, { name: "Apples", price: 5 }] }, { category: "B", items: [{ name: "Bread", price: 5 }] }], [{ category: "C", items: [{ name: "Candy", price: 5 }, { name: "Crayon", price: 5 }] }, { category: "D", items: [{ name: "Dice", price: 5 }, { name: "Doll", price: 10 }] }]] } }
console.log(flat(object));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am trying to figure out how to group by at multiple levels:
Given the following input JSON:
[
{
"GroupingMajor": "Fruit",
"Grouping": "Banana",
"Description": "10 Bananas",
"Price": 20609.82,
},
{
"GroupingMajor": "Fruit",
"Grouping": "Apple",
"Description": "13 Apples",
"Price": 4567.98,
},
{
"GroupingMajor": "Dairy",
"Grouping": "Cheese",
"Description": "1 KG",
"Price": 76456.76,
}
]
I would like to create output of type:
{
"name": "root",
"children": [
{
"name": "Fruit",
"children": [
{
{"name": "Apple", "price": 4567.98},
{"name": "Banana", "price": 20609.82}
}]
},
{
"name": "Dairy",
"children": [
{
{"name": "Cheese", "price": 76456.76}
}]
}]
}
That is, data is grouped by "GroupingMajor" and then "Grouping". "Grouping" being a child of the parent "GroupingMajor" category. How can I generate this output using linq.js (JavaScript)?
Here is some JavaScript that I've attempted:
var data = Enumerable.From(dataFood)
.GroupBy(
function (e) {
return {
groupmajor: e.GroupingMajor,
groupminor: e.Grouping
}},
function (e) {
return {
groupmajor: e.GroupingMajor,
groupminor: e.Grouping,
name: e.GroupingMajor,
price: e.Price,
}
},
function (key, g) {
return {
group: key.groupmajor,
groupminor: key.groupminor,
name: g.name,
price: g.price
}
})
.ToArray();
I am not getting a correct grouping and I have no idea how to generate a sub-group.
Any help is appreciated.
Here's how you could construct such a query:
var query = Enumerable.From(data)
.GroupBy(
"$.GroupingMajor", // key
"{ name: $.Grouping, price: $.Price }", // item
"{ name: $, children: $$.ToArray() }" // result
)
.ToArray();
var result = {
name: 'root',
children: query
};
Which would yield the following result:
{
"name": "root",
"children": [
{
"name": "Fruit",
"children": [
{
"name": "Banana",
"price": 20609.82
},
{
"name": "Apple",
"price": 4567.98
}
]
},
{
"name": "Dairy",
"children": [
{
"name": "Cheese",
"price": 76456.76
}
]
}
]
}
I can't figure out why this tree 'flattener' is returning only innermost children, the expectation is that it should return flattened tree.
var x = {
"Fields": {
"Id": "1",
"MasterAccountId": "",
"ParentAccountId": "",
"Name": "Name 1"
},
"Children": [{
"Fields": {
"Id": "2",
"MasterAccountId": "1",
"ParentAccountId": "1",
"Name": "Name 2"
},
"Children": [{
"Fields": {
"Id": "5",
"MasterAccountId": "1",
"ParentAccountId": "2",
"Name": "Name 5"
},
"Children": [{
"Fields": {
"Id": "6",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 6"
}
}, {
"Fields": {
"Id": "7",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 7"
}
}]
}]
}]
}
function recurs(n) {
console.log(n.Fields.Name);
return (n.Children != undefined ? $.map(n.Children, recurs) : n);
}
var r = recurs(x);
It returns elements with id 6, 7, while console.logs all 5 of them.
http://plnkr.co/edit/LdHiR86EDBnZFAh6aAlG?p=preview
Your function only returns n if n.Children is undefined. Since you want a flat array with all the objects you have to build one.
function recurs(n) {
var out = [];
out.push(n.Fields);
if (n.Children) {
for (var i=0, c; c = n.Children[i]; i++) {
out.push.apply(out, recurs(c));
}
}
return out;
}