I want to use the library markdown-table to generate out of my object a table. The pre-requirement is to create an array with a certain structure.
Find below my minimum viable example:
const obj = {
"2": {
"title": "Product 1",
"category": [{
"cat_name": "Graphic Card"
}],
"currency": "$",
"price": "513.40"
},
"3": {
"title": "Product 2",
"category": [{
"cat_name": "Graphic Card"
}],
"currency": "$",
"price": "599.00",
},
"4": {
"title": "Memory Ram 1",
"category": [{
"cat_name": "Memory"
}],
"currency": "$",
"price": "25.99",
},
"5": {
"title": "Product 3",
"category": [{
"cat_name": "Graphic Card"
}],
"currency": "$",
"price": "688.88",
},
"6": {
"title": "Adapter 1",
"category": [{
"cat_name": "PCI-E"
}],
"currency": "$",
"price": "48.99",
}
}
var result = Object.keys(obj).map(function(key) {
return [Number(key), obj[key]];
});
console.log(result)
<script src="https://raw.githubusercontent.com/wooorm/markdown-table/master/index.js"></script>
I am getting the following result for my table:
| 2 | [object Object] |
| --- | --------------- |
| 3 | [object Object] |
| 4 | [object Object] |
| 5 | [object Object] |
| 6 | [object Object] |
However, the result array I am trying to get should look like the following:
[
['Category', 'Model', 'Price'],
['Graphic Card', 'Prod 1', '$513.40'],
['Graphic Card', 'Product 2', '$599.00'],
['Graphic Card', 'Product 3', '$688.88'],
['Memory', 'Memory Ram 1', '$25.99'],
['PCI-E', 'Adapter 1', '$48.99']
]
Any suggestions why my array is not parsed correctly and [object Object] is shown?
I appreciate your replies!
[object Object] what you get when you call .toString() on an object.
It looks like you need to explicitly pass markdown-table the values you want displayed, as all it's doing is calling .toString() on what you pass in. I don't see where it will derive the headers and values for you.
Something like this might do the trick:
let result = Object.keys(obj)
.reduce((result, key) => {
result.push([obj[key].category[0].cat_name, obj[key].title, obj[key].currency + obj[key].price]);
return result;
},
[['Category', 'Model', 'Price']]
);
What's going on here is I'm passing in the headers as the initial value of the accumulator in .reduce(), and each iterations is pushing a row of values onto the accumulated array.
If you want to sort the results:
let result = Object.keys(obj)
.sort((a, b) => {
if (obj[a].category[0].cat_name < obj[b].category[0].cat_name)
return -1;
if (obj[a].category[0].cat_name > obj[b].category[0].cat_name)
return 1;
if (obj[a].model < obj[b].model)
return -1;
if (obj[a].model > obj[b].model)
return 1;
return 0;
})
.reduce(...
Here's a fiddle: https://jsfiddle.net/jmbldwn/t8Lvw2bj/2/
You can use Object.values() to get the values from your object and then using array#map with object and array destructuring you can generate the desired array. Then using local#compare and array#sort, sort the array alphabetically. Then you using array#unshift you can add the ['Category', 'Model', 'Price'] at the beginning of array.
const obj = { "2": {"title": "Product 1", "category": [{ "cat_name": "Graphic Card" }], "currency": "$", "price": "513.40" }, "3": { "title": "Product 2", "category": [{ "cat_name": "Graphic Card" }], "currency": "$", "price": "599.00", }, "4": { "title": "Memory Ram 1","category": [{ "cat_name": "Memory" }], "currency": "$", "price": "25.99", }, "5": { "title": "Product 3", "category": [{ "cat_name": "Graphic Card" }], "currency": "$", "price": "688.88", }, "6": { "title": "Adapter 1", "category": [{ "cat_name": "PCI-E"}], "currency": "$", "price": "48.99", } };
let result = Object
.values(obj)
.map(({title, category : [{cat_name}], currency, price}) => [cat_name, title, `${currency}${price}`])
.sort((a,b) => a[0].localeCompare(b[0]) || a[1].localeCompare(b[1]));
result.unshift(['Category', 'Model', 'Price']);
console.log(result);
Related
I have restaurant data array , I should make another array by grouping items by category that belongs to , I should convert this array :
[
{
"category": {
"title": "Appetizers",
},
"id": 1,
"price": "10",
"title": "Spinach Artichoke Dip",
},
{
"category": {
"title": "Appetizers",
},
"id": 2,
"price": "10",
"title": "Hummus",
},
{
"category": {
"title": "Salads",
},
"id": 3,
"price": "7",
"title": "Greek",
},
{
"category": {
"title": "Salads",
},
"id": 4,
"price": "9",
"title": "Beyn",
}
]
into a new array that should be as final result like this:
[{
"category": "Appetizers",
"items" : ["Spinach Artichoke Dip","Hummus"]
},
{
"category" : "Salads",
"items" :["Greek", "Beyn"]
}
]
I can't find how to do it could you please help
Lets say that your data is a constant called data
So you can do this:
const data = [
{
"category": {
"title": "Appetizers",
},
"id": 1,
"price": "10",
"title": "Spinach Artichoke Dip",
},
{
"category": {
"title": "Appetizers",
},
"id": 2,
"price": "10",
"title": "Hummus",
},
{
"category": {
"title": "Salads",
},
"id": 3,
"price": "7",
"title": "Greek",
},
{
"category": {
"title": "Salads",
},
"id": 4,
"price": "9",
"title": "Beyn",
}
];
const result = [];
data.forEach((item) => {
const category = item.category.title;
const title = item.title;
let foundCategory = result.find((c) => c.category === category);
if (foundCategory) {
foundCategory.items.push(title);
} else {
result.push({ category, items: [title] });
}
});
console.log(result);
Now your desired result will be stored in result
happy coding
const itemsToCategories = (itemsArr) => {
const store = {};
itemsArr.forEach(item => {
const categoryTitle = item.category.title;
if (!store[categoryTitle]) store[categoryTitle] = [];
store[categoryTitle].push(item.title);
});
return Object.entries(store).map(([category, items]) => ({ category, items}));
};
This solution should be a bit faster than the accepted answer for large data sets. The main difference is the use of an object (store) instead of an array, so lookups by the category title are more efficient. Then we build an array from that object at the end.
This does have more overhead than the accepted solution above, so for smaller data sets, this ends up being slower in comparison.
Hey guys I have the following array that's used to display a flatlist within my app.
Array [
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "1,16,19",
},
]
However I would like to sort this array based off the subjects value. In the app the user can select a couple of subjects which are represented by numbers so lets say the users selected subjects are:
11, 4, 2, 1
I would like to sort the array so that the items with 3 or more subjects in common with the user are sorted to the top and then items with two and then 1 and then none so the array above should look like this after sorting:
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
},
]
How can I achieve this?
I have been searching around the array sort function:
Array.prototype.sort()
However I have only seen how to sort based off number comparisons I have never seen an array sorted based off values in common. Please could someone help me with this!
EDIT
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
"ranking": "green",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
"ranking": "amber",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
"ranking": "amber",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
"ranking": "red",
},
]
You could create an object with counts of selected subjects and sort descending by this value.
const
data = [{ data: "Item 1", id: "1", subjects: "1,8,9,23,11,15,16,14,20" }, { data: "Item 2", id: "2", subjects: "8,11,2,4,16,19" }, { data: "Item 3", id: "3", subjects: "16,20,14,11,9,2" }, { data: "Item 4", id: "4", subjects: "1,16,19" }],
selected = [11, 4, 2, 1],
counts = data.reduce((r, { id, subjects }) => {
r[id] = subjects
.split(',')
.reduce((s, v) => s + selected.includes(+v), 0);
return r;
}, {});
data.sort((a, b) => counts[b.id] - counts[a.id]);
console.log(data);
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have this JSON response where I want to push "status": "pending", inside the nested Menu array, Please help how I can achieve this in Javascript.
[
{
"id": 1,
"status": "pending",
"menues": [
{
"title": "Coke",
"price": "200"
}
]
},
{
"id": 2,
"status": "delivered",
"menues": [
{
"title": "Pepsi",
"price": "120"
}
]
}
]
Here is what I want to achieve:
I just want to push the Staus key/value inside the Menu array
[
{
"id": 1,
"menues": [
{
"title": "Coke",
"price": "200",
"status": "pending",
}
]
},
{
"id": 2,
"menues": [
{
"title": "Pepsi",
"price": "120",
"status": "delivered",
}
]
}
]
You can go over the array, and for each item, go over the items in menues. Using the forEach method, this can even be done as a single statement:
arr = [
{
"id": 1,
"status": "pending",
"menues": [
{
"title": "Coke",
"price": "200"
}
]
},
{
"id": 2,
"status": "delivered",
"menues": [
{
"title": "Pepsi",
"price": "120"
}
]
}
];
arr.forEach(nested => {
nested.menues.forEach(menu => menu.status = nested.status);
delete nested.status
});
console.log(arr);
Maybe this is what you want? The following script creates a new nested array structure, leaving the original unchanged. Instead of deleting the status property from the outer object I limit the creation of properties in the newly created object to id and menues.
I changed this answer in response to OP's comment asking for ES5 and ES6 methods and the ... operator.
arr = [
{
"id": 1,
"status": "pending",
"menues": [
{
"title": "Coke",
"price": "200"
}
]
},
{
"id": 2,
"status": "delivered",
"menues": [
{
"title": "Pepsi",
"price": "120"
}
]
}
];
const res=arr.map(nested =>({ id:nested.id, menues:
nested.menues.map(menu =>({...menu,status:nested.status})) }));
console.log(res);
As an example - I've included a one element array that contains an object that has a Children key, which is an array of objects and each object also has its' own Children key that contains another array.
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
{
"Id": "100",
"DisplayName": "1-2",
},
]
}
]
}
]
There is a second array of objects that I would like to compare the first array of objects to, with the intention of making sure that the first array is in the same order as the second array of objects, and if it is not - then sort until it is.
Here is the second array:
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "100",
"DisplayName": "1-2",
},
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
]
}
]
}
]
The data that this will run on can be up in the tens of thousands - so performance is paramount.
What I'm currently attempting is using a utility method to convert each element of the second array into a keyed object of objects e.g.
{
1: {
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}
]
}
}
This allows fast look up from the top level. I'm wondering if I should continue doing this all the way down or if there is an idiomatic way to accomplish this. I considered recursion as well.
The order of the already sorted array is not based on Id - it is arbitrary. So the order needs to be preserved regardless.
Assuming same depth and all Id's exist in each level of each object use a recursive function that matches using Array#findIndex() in sort callback
function sortChildren(main, other) {
other.forEach((o, i) => {
if (o.children) {
const mChilds = main[i].children, oChilds = o.children;
oChilds.sort((a, b) => {
return mChilds.findIndex(main => main.Id === a.Id) - mChilds.findIndex(main => main.Id === b.Id)
});
// call function again on this level passing appropriate children arrays in
sortChildren(mChilds, oChilds)
}
})
}
sortChildren(data, newData);
console.log(JSON.stringify(newData, null, ' '))
<script>
var data = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "3",
"DisplayName": "1-2",
},
{
"Id": "4",
"DisplayName": "3-4",
},
]
}]
}]
var newData = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}]
}]
</script>
[
{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
},
{
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}]
I have many of this objects and need to take Customer and sum (add) all of his "Hs" value. So the final array would be like:
[
{
"Customer" : "Infranet",
"Total_hs" : "18"
},
{
"Customer" : "Huxley",
"Total_hs" : "11"
}
]
I tried to find out with lodash and node foreach functions but can't, could you help me please? Thanks!
First, you must make sure you have the input data as a javascript object (so if it is a json string, it will need to be parsed with something like var items = JSON.parse(input_string))
var items = [{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
}, {
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}]
... next, create array of summed Hs values...
var totals = _.reduce(items, function(memo, item) {
// make sure that the customer is created on the output object, or initialise it to zero
memo[item.Customer] = memo[item.Customer] || 0;
// increment the Hs value with the current item's Hs value
memo[item.Customer] += item.Hs;
// return the current object for the next iteration of the loop
return memo;
// pass empty object to initialise reduce
}, {});
totals should now have array of objects, with customer name as key, and total Hs as value.
... next, reformat array to match desired data format...
var target_array = _.map(totals, function(item, key) {
return {
Customer: key,
Total_hs: item
}
});
... check the out put is correct...
console.log(target_array);
Given the JSON is provided as a JavaScript object (items in the sample below):
var items = [{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
}, {
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}];
var collected = _.map(_.keys(_.grouped(items, "Customer")), function(k) {
return {
Customer: k,
Hs: _.reduce(grouped[k], function(accumulator, v) {
return accumulator + v.Hs;
}, 0)
};
});