React object to array to print out on frontend using .map - javascript

i actually have return 2 types of result from 1 API call
{
"data1": [
{
"item_name": "item 4",
"price_updated_date": "2022-04-14T08:05:16.339Z",
"item_img_id": "https://testing.jpg",
"set_name": "2017",
"set_tag": "mm3",
"rarity": "rare",
"price_normal": 34.99,
"price_foil": 54.99
},
],
"data2": [
{
"item_condition": "NM",
"item_img": "https://test.jpg",
"item_name": "item 1",
"item_set": "ZEN",
"item_language": "JP",
"item_type": "Non Foil",
"item_price": "¥ 4,580",
"item_qty": 9,
"other_condition": {
"SP": {
"qty": 1,
"price": "¥ 3,670"
},
"MP": {
"qty": 1,
"price": "¥ 3,210"
}
}
},
{
"item_condition": "NM",
"item_img": "https://0010.jpg",
"item_name": "item 3",
"item_set": "ZNE",
"item_language": "JP",
"item_type": "Non Foil",
"item_price": "¥ 8,000",
"item_qty": 6,
"other_condition": {
"MP": {
"qty": 1,
"price": "¥ 6,400"
}
}
},
]
}
from the return, they are all Object, so i need to make a conversion to Array in order to print them out on my frontend with .map so i use this
const convertObjToArr = (responseObj) => {
let arr = []
Object.keys(responseObj).forEach(function(key) {
arr.push(responseObj[key]);
});
return arr
}
convertObjToArr(data.data1)
convertObjToArr(data.data2)
however, my data2 has another object inside it as well call "other_condition" which is not converting to Array and is still in Object. When i tried to display it with .map, it gives me error. In this case, how can i handle that object to array? is there any way to convert all of them into Array regardless how many nested object i have in one data?

Does this help?
const renderThisItem = itm => {
/*console.log(
'itm: ', itm,
'typeof: ', typeof itm,
'keys: ', Object.keys(itm)
);*/
if (itm) {
if (typeof itm === 'string' || typeof itm === 'number') {
return (<div>{itm},</div>);
} else if (Array.isArray(itm)) {
return (
<div>[{
itm.map(it => renderThisItem(it))
}],</div>
)
} else if (Object.keys(itm).length > 0) {
return (
<div>{"{"} {
Object.entries(itm)
.map(([k, v]) => (
<div>
<div class="val">{k}: {renderThisItem(v)}</div>
</div>
))
} {"},"}</div>
)
}
};
};
const Thingy = ({ dataObj, ...props }) => {
return (
<div>{renderThisItem(dataObj)}</div>
);
};
const rawData = {
"data1": [
{
"item_name": "item 4",
"price_updated_date": "2022-04-14T08:05:16.339Z",
"item_img_id": "https://testing.jpg",
"set_name": "2017",
"set_tag": "mm3",
"rarity": "rare",
"price_normal": 34.99,
"price_foil": 54.99
},
],
"data2": [
{
"item_condition": "NM",
"item_img": "https://test.jpg",
"item_name": "item 1",
"item_set": "ZEN",
"item_language": "JP",
"item_type": "Non Foil",
"item_price": "¥ 4,580",
"item_qty": 9,
"other_condition": {
"SP": {
"qty": 1,
"price": "¥ 3,670"
},
"MP": {
"qty": 1,
"price": "¥ 3,210"
}
}
},
{
"item_condition": "NM",
"item_img": "https://0010.jpg",
"item_name": "item 3",
"item_set": "ZNE",
"item_language": "JP",
"item_type": "Non Foil",
"item_price": "¥ 8,000",
"item_qty": 6,
"other_condition": {
"MP": {
"qty": 1,
"price": "¥ 6,400"
}
}
},
]
};
ReactDOM.render(
<div>
DEMO
<Thingy dataObj={rawData} />
</div>,
document.getElementById('rd')
);
.val { display: flex; }
<div id="rd" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

How to filtering out the multiple nested object in Javascript object

Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));

How to group by and sum an array of objects javascript?

const array = [
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
}
]
var result = [];
array.reduce(function(res, value) {
if (!res['data']['toy'] || !res['data']['toy']['data']) {
res['data'] = {...value['data'] };
result.push(res['data'])
}
if (res['data']['available'] === value['data']['available'] && res['data']['toy']['id'] === value['data']['toy']['id']) {
res['data']['qty'] = parseInt(res['data']['qty']) + parseInt(value['data'].qty)
}
return res;
}, {'data': {}});
console.log(result)
I am working on a js project and I need a bit of help here. From the array, How to get a new array that has qty as the sum of the other qty value which data.toy.id and available same. i.e. I want the below array. My code is not working as excepted. Changes to the same or new code are also fine. Thank you.
const array = [
{
"data": {
"qty": "10",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
}
]
You group the array into an object, where the keys are concatenation of available and id properties and finally transform the object back to an array using Object.values.
const
array = [
{ data: { qty: "5", toy: { id: 3 }, available: "yes" } },
{ data: { qty: "5", toy: { id: 10 }, available: "no" } },
{ data: { qty: "59", toy: { id: 10 }, available: "yes" } },
{ data: { qty: "5", toy: { id: 3 }, available: "yes" } },
],
result = Object.values(
array.reduce((r, { data }) => {
const k = data.available + data.toy.id;
if (r[k]) {
r[k].data.qty = String(Number(r[k].data.qty) + Number(data.qty));
} else {
r[k] = { data };
}
return r;
}, {})
);
console.log(result);
I'd suggest using Array.reduce() to group by a key, which will be combined value of the toy id and the available property.
We'd create a map of all toys based on this key, summing the quantity for each.
Finally, we'll use Object.values() to convert back into an array.
const array = [ { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 10, }, "available": "no" } }, { "data": { "qty": "59", "toy": { "id": 10, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } } ];
const result = Object.values(array.reduce((acc, { data: { qty, toy, available } }) => {
const key = `${toy.id}-${available}`;
acc[key] = acc[key] || { data: { qty: 0, toy, available } };
acc[key].data.qty += Number(qty);
return acc;
}, {}))
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
You can use Array#reduce() to create arrayHash object using as keys: ${c.data.toy.id}-${c.data.available}
Code:
const array = [{data: {qty: '5',toy: {id: 3,},available: 'yes',},},{data: {qty: '5',toy: {id: 10,},available: 'no',},},{data: {qty: '59',toy: {id: 10,},available: 'yes',},},{data: {qty: '5',toy: {id: 3,},available: 'yes',},},]
const arrayHash = array.reduce((a, { data }) => {
const key = `${data.toy.id}-${data.available}`
a[key] = a[key] || { data: { ...data, qty: 0 } }
a[key].data.qty = (+a[key].data.qty + +data.qty).toString();
return a
}, {})
const result = Object.values(arrayHash)
console.log(result)
I'd use just reduce
const a1 = [
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
}
]
const a2 = a1.reduce((acc, it) => {
let found = acc.find(
dp => dp.data.toy.id === it.data.toy.id && dp.data.available === it.data.available
)
if(found){
found.data.qty = ( Number(found.data.qty) + Number(it.data.qty) ).toString()
}
else acc.push(it)
return acc
}, [])
console.log(JSON.stringify(a2, null,2))

Get object value based on conditions within nested array objects

I have an array of objects called orders:
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}
]
}
];
I need to get the quantity when both the order_type (Wholesale) and items.detail.ID (13363) match.
I have so far tried the following:
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if(item.detail.ID == 13363) {
return item.quantity;
}
}, 0);
Where result correctly returns 4
My issue, and I'm sure I am missing something very simple is that when I have multiple items in my orders array, it fails.
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
},
{
"id": 56,
"department": "Womens",
"type": "Skirt",
"quantity": 12,
"detail": {
"ID": 76884,
"On Sale": 0,
}
},
{
"id": 89,
"department": "Mens",
"type": "Shirts",
"quantity": 20,
"detail": {
"ID": 98223,
"On Sale": 1,
}
}
]
}
];
The same
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if(item.detail.ID == 13363) {
return item.quantity;
}
}, 0);
returns undefined
Thank you
The find helper just returns the first match, so you need to use another helper like filter, like this:
const ID = 13363;
const result = orders
.filter((order) => order.order_type === 'Wholesale')
.reduce((acc, curr) => {
const items = curr.items.filter((item) => item.detail.ID === ID);
console.log(items);
// You can sum the matching items and then push them into the acc array
const quantity = items.reduce((sum, item) => (sum += item.quantity), 0);
acc.push(quantity);
return acc;
}, []);
This will return an array of matching quantities.
Not sure about the use case but here you go
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if (item.detail.ID == 13363) {
total += item.quantity;
}
return total
}, 0);
You can even create a function to make the search dynamic.
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
},
{
"id": 56,
"department": "Womens",
"type": "Skirt",
"quantity": 12,
"detail": {
"ID": 76884,
"On Sale": 0,
}
},
{
"id": 89,
"department": "Mens",
"type": "Shirts",
"quantity": 20,
"detail": {
"ID": 98223,
"On Sale": 1,
}
}
]
}
];
findMyItem=( ID )=>{
var result = null ;
const result2 = orders.find(item => item.order_type == "Wholesale").items
.map(( item) => {
if(item.detail.ID == ID ) {
result = item.quantity;
}
}, 0);
return result ;
}
console.log( "result" ,findMyItem( 13363 ) )
console.log( "result" ,findMyItem( 98223) )
console.log( "result" ,findMyItem( 76884) )
You could use Array.find() on the orders array to find the correct order, searching for the first order that matches both the order_type and has an item matching the desired itemId (using Array.some()).
If this order exists, we can then find the corresponding item quantity using .find() again,
const orders = [ { "order_id": 47445, "order_type": "Wholesale", "items": [ { "id": 9, "department": "Womens", "type": "Dress", "quantity": 4, "detail": { "ID": 13363, "On Sale": 1, } }, { "id": 56, "department": "Womens", "type": "Skirt", "quantity": 12, "detail": { "ID": 76884, "On Sale": 0, } }, { "id": 89, "department": "Mens", "type": "Shirts", "quantity": 20, "detail": { "ID": 98223, "On Sale": 1, } } ] } ]
function findItemQuantity(orders, orderType, itemId) {
// Find the first order with the right order_type and containing the right item id
const order = orders.find(order => order.order_type = orderType && order.items.some(item => item.detail.ID === itemId));
if (!order) {
return null;
}
const item = order.items.find(item => item.detail.ID === itemId);
if (!item) {
return null;
}
return item.quantity;
}
console.log("Quantity found:", findItemQuantity(orders, 'Wholesale', 13363))
console.log("Quantity found:", findItemQuantity(orders, 'Wholesale', 76884))
const result = orders
.filter(order => order.order_type == "Wholesale")
.map(order => order.items.find(item => item.detail.ID == 13363))
.filter(item => item)
.reduce((total, { quantity }) => quantity + total, 0);
const orders = [{
"order_id": 47445,
"order_type": "Wholesale",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
},
{
"order_id": 47445,
"order_type": "Whole",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
}
]
const result = orders.reduce(v => {
return v.items.map(a => {
if (v.order_type == 'Wholesale' && a.detail.ID == 13363) {
return v
}
})
})
console.log(result)
const orders = [{
"order_id": 47445,
"order_type": "Wholesale",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
}];
var result = null;
const result2 = orders.find(item => item.order_type == "Wholesale").items
.map((item) => {
if (item.detail.ID == 98223) {
result = item.quantity;
}
}, 0);
console.log("result", result)

How to find a value in multilevel Array of objects

I'm trying to implement a search box in which if i start searching for a value it will look for the target in an nested array of objects which is like this:--
[
{
"groupId": 1,
"groupName": "Americas",
"groupItems": [
{
"id": 5,
"name": "Brazil",
"parentID": 1,
"parentName": "Americas"
},
{
"id": 6,
"name": "Canada",
"parentID": 1,
"parentName": "Americas"
}
],
"isExpanded": false,
"toggleAllSelection": false
},
{
"groupId": 2,
"groupName": "APAC",
"groupItems": [
{
"id": 7,
"name": "Australia",
"parentID": 2,
"parentName": "APAC"
},
{
"id": 8,
"name": "China",
"parentID": 2,
"parentName": "APAC"
}
],
"isExpanded": false,
"toggleAllSelection": false
},
{
"groupId": 3,
"groupName": "Europe",
"groupItems": [
{
"id": 9,
"name": "Belgium",
"parentID": 3,
"parentName": "Europe"
},
{
"id": 7,
"name": "Austria",
"parentID": 2,
"parentName": "APAC"
},
{
"id": 10,
"name": "Bulgaria",
"parentID": 3,
"parentName": "Europe"
}
],
"isExpanded": false,
"toggleAllSelection": false
}
]
Now i want to search for name property in each groupItems array of objects in group array. and when there is a match my function should return data in same format and as it will be autocomplete so instead of exact match it should be partial match. So if search aus in input box it should return
[{
"groupId": 2,
"groupName": "APAC",
"groupItems": [
{
"id": 7,
"name": "Australia",
"parentID": 2,
"parentName": "APAC"
}],
"isExpanded": false,
"toggleAllSelection": false,
},
{
"groupId": 3,
"groupName": "Europe",
"groupItems": [
{
"id": 7,
"name": "Austria",
"parentID": 2,
"parentName": "APAC"
}
],
"isExpanded": false,
"toggleAllSelection": false
}
]
const findByName = (data, name) => {
const result = data.reduce((m, { groupItems, ...rest }) => {
let mapGrpItems = (groupItems || []).filter((item) =>
item.name.includes(name)
);
if (mapGrpItems.length) {
m.push({ ...rest, groupItems: mapGrpItems });
}
return m;
}, []);
return result;
};
const findByName = (data, name) => {
const result = data.reduce((m, { groupItems, ...rest }) => {
let mapGrpItems = (groupItems || []).filter((item) =>
item.name.includes(name)
);
if (mapGrpItems.length) {
m.push({ ...rest, groupItems: mapGrpItems });
}
return m;
}, []);
return result;
};
const data = [{"groupId":1,"groupName":"Americas","groupItems":[{"id":5,"name":"Brazil","parentID":1,"parentName":"Americas"},{"id":6,"name":"Canada","parentID":1,"parentName":"Americas"}],"isExpanded":false,"toggleAllSelection":false},{"groupId":2,"groupName":"APAC","groupItems":[{"id":7,"name":"Australia","parentID":2,"parentName":"APAC"},{"id":8,"name":"China","parentID":2,"parentName":"APAC"}],"isExpanded":false,"toggleAllSelection":false},{"groupId":3,"groupName":"Europe","groupItems":[{"id":9,"name":"Belgium","parentID":3,"parentName":"Europe"},{"id":7,"name":"Austria","parentID":2,"parentName":"APAC"},{"id":10,"name":"Bulgaria","parentID":3,"parentName":"Europe"}],"isExpanded":false,"toggleAllSelection":false}]
console.log(JSON.stringify(findByName(data, "Aus"), null, 2));
I would definitely attempt to reason through what you're trying to do before just implementing this. Being able to reason through solutions like this is 99% of the job when it comes to programming.
function filterGroups(filter) {
const result = [];
myObj.forEach(group => {
const filteredGroups = group.groupItems.filter(groupItem => {
return groupItem.name.toLowerCase().includes(filter);
});
if (filteredGroups.length > 1) {
result.push({
...group,
groupItems: filteredGroups
});
}
});
return result;
}
You can use Arrays.filter for the group items in each outer object in your JSON array to filter out the items which match your search query. You can write something like this:
let autocomplete = (key) => {
// arr = Your Data
let result = []
arr.forEach(grp=> {
let out = grp
let res = grp.groupItems.filter(item => item.name.toLowerCase().includes(key.toLowerCase()))
if(res.length!=0)
{
out.groupItems = res
result.push(out)}
})
return result

Get last deepest level item in object

I have data and function like this:
const lodash = require('lodash')
var data = [
{
"nextStep": [
{
"nextStep": [
{
"nextStep": [
{
"nextStep": [],
"student": {
"name": "Alice",
"grade": 1
}
}
],
"student": {
"name": "Lisa",
"grade": 2
}
}
],
"student": {
"grade": 3,
"name": "This is GS"
}
}
],
"student": {
"grade": 4,
"name": "Paul"
}
}
]
function searchByJsonPath(path, obj, target) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (k === target)
return path;
else if (typeof obj[k] === "object") {
var result = searchByJsonPath(path + "." + k, obj[k], target);
if (result)
return result;
}
}
return false;
}
I want to get the last item in object, the result should be
"name": "Alice",
"grade": 1
So I call the searchByJsonPath to get the path and use the lodash to get an item
test = searchByJsonPath('data', data, 'name');
but test = data.0.nextStep.0.nextStep.0.nextStep.0.student
the correct path should be data[0].nextStep[0].nextStep[0].nextStep[0].student
Please advice me.
You can try recursion like below to get the deepest element
var data = [{ "nextStep": [ { "nextStep": [ { "nextStep": [ { "nextStep": [], "student": { "name": "Alice", "grade": 1 } } ], "student": { "name": "Lisa", "grade": 2 } } ], "student": { "grade": 3, "name": "This is GS" } } ], "student": { "grade": 4, "name": "Paul" }}]
function getData(obj) {
return obj.nextStep.length > 0
? getData(obj.nextStep[0])
: obj.student
}
console.log(getData(data[0]))

Categories