sort objects in array with dynamic keys - javascript

I am trying to sort an array of dynamic key / values (Object) based on a property in the object. Can someone please provide me an example of how to do this. Ill try to create a similar structure to my issue
Order Class:
export class order {
id: number;
productRank: number;
productId: number;
productName: string;
}
There is a storeOrders observable array of orders in my component
storeOrders$: Observable<Array<orders>>;
The key in the orders array is dynamically generated and is stored with the key/value containing as key and order object as value
then the orders object for example is something like:
let orders = {
12_123: { id: 123, productRank: 3, productId: 23, productName: 'shirt'},
23_124: { id: 124, productRank: 1, productId: 14, productName: 'cologne'},
67_124: { id: 125, productRank: 2, productId: 45, productName: 'belt' }
}
When i subscribe to this data, how can I iterate over the storeOrders array and sort items based on the productRank. I have been trying to get this right but was not able to get this working, can someone please point out how to iterate over dynamic keys in an array and do a sort based on a property in the value object? Thank you, your helps really appreciated!

Your orders should be a object as below,
orders = {
12_123: { id: 123, productRank: 3, productId: 23, productName: 'shirt' },
23_124: { id: 124, productRank: 1, productId: 14, productName: 'cologne' },
67_124: { id: 125, productRank: 2, productId: 45, productName: 'belt' }
};
you can form the values by using Object.values(orders)
I use sortBy from lodash library as I'm used to it and you get the sorted values as
console.log(sortBy(Object.values(orders),['productRank']));
Stackblitz

to order a dynamic array of keys/values you can do this :
example of array :
arr = [
{de : 'germany'},
{fr : 'france'},
{uk : 'united kingdom'},
{tn : 'tunisia'}
]
arr.sort((a, b) => {
const a_key = Object.keys(a);
const a_value = a[a_key];
const b_key = Object.keys(b);
const b_value = b[b_key];
if (a_value == b_value) return 0;
return a_value > b_value ? 1 : -1;
});
that's all !

Related

How do I incorporate the index of an array while defining a property of said array within a class in JavaScript?

Sorry if the title makes no sense.. let me explain
Say I have the following 2d array.. the first array representing ice cream and the second representing milkshakes
menu = [ ['vanilla', 'chocolate', 'almond'],
['vanilla', 'pineapple', 'strawberry'] ]
Now I create a class that takes this array as input
class cafe{
constructor(menu){
this.iceCreams = menu[0]
this.milkshakes = menu[1]
}
}
Now I want to define a property called 'price' for each flavor of milkshake.
this.milkshakes[n].price = < a function that computes price based on value of n >
so that i can access them like this :
cafe.milkshakes[0].price
So how do I incorporate the index 'n' of the array while defining the property
I haven't tried anything bcos I dont know how to even approach this ☹️
You can do it in your constructor.
You can grab the names, and call map function on it and do whatever you want. Please check the following example. There, calculatePrice is a function that takes the index and returns the price based on the index.
class Cafe {
constructor (menu) {
this.iceCreams = menu[0].map((flavor, index) => {
return {
flavor,
price: calculatePrice(index)
}
});
this.milkshakes = menu[1].map((flavor, index) => {
return {
flavor,
price: calculatePrice(index)
}
});
}
This is a minimal answer.
UPDATE:
For a detailed and improved answer: https://codesandbox.io/s/cafe-example-wxp2c4
So, in the milkshakes array you need each item as an object data structure, not a string.
menu = [ ['vanilla', 'chocolate', 'almond'],
[{ flavor: 'vanilla' }, { flavor: 'pineapple' }, { flavor: 'strawberry' }] ]
and then you can loop through and set the price, something like this.
menu.milkshakes.forEach((item, index) => item.price = index))
you can use objects:
menu = [
[
{
name: "vanilla",
price: 200,
},
{
name: "chocolate",
price: 200,
},
{
name: "almond",
price: 200,
},
],
[
{
name: "vanilla",
price: 200,
},
{
name: "pineapple",
price: 200,
},
{
name: "strawberry",
price: 200,
},
],
];
and then:
class cafe{
constructor(menu){
this.iceCreams = menu[0]
this.milkshakes = menu[1]
}
}
now iceCreams and milshakes have the property price and name
example:
iceCreams[n].price
iceCreams[n].name

Group by list of dictionary in javascript

Input =
[{id: 13, display_name: "Customizable Desk (Aluminium, Black)", quantity: 4, unit_price: "800.40", discount: 0, price: "3201.60"},
{id: 40, display_name: "Magnetic Board", quantity: 2, unit_price: "1.98", discount: 0, price: "3.96"},
{id: 40, display_name: "Magnetic Board", quantity: 1, unit_price: "1.98", discount: 0, price: "1.98"},
{id: 40, display_name: "Magnetic Board", quantity: 1, unit_price: "1.98", discount: 0, price: "1.98"}]
Output =
[{id: 13, display_name: "Customizable Desk (Aluminium, Black)", quantity: 4, unit_price: "800.40", discount: 0, price: "3201.60"},
{id: 40, display_name: "Magnetic Board", quantity: 4, unit_price: "1.98", discount: 0, price: "7.92"}]
I am able to achieve an answer but my process is very lengthy, I need a short answer for it using some predefined functions of javascript.
Here's a short way to do this (based on the assumption I cited before that quantity is the only thing that can vary for each item with the same id value):
inputArray.reduce((result, item) => {
if (result.map.has(item.id)) {
result.map.get(item.id).quantity += item.quantity;
} else {
result.array.push(item);
result.map.set(item.id, item);
}
return result;
}, {map: new Map(), array: []}).array
This uses the array reduce function, if you're not familiar with that. This could be done without the Map, but that makes it more efficient than searching through the whole result array to find id values which have already been seen.
The idea behind this code is that you keep the first item you see that has an id that you haven't seen before, and if you have seen an id before, you look up that original item, and add the new quantity to the previous quantity.
I'd do something like this:
function groupProducts( input ) {
var productsById = input.reduce( function( current, item ) {
if( !current[ item.id ] ) {
current[ item.id ] = [];
}
current[ item.id ].push( item );
return current;
}, {} );
return Object.keys( productsById ).map( function( id ) {
productsById[ id ].reduce( function( current, item ) {
if( current ) {
// this could be extracted as a closure passed in to coalesce items together. Your rules for how that happens go here.
current.quantity += item.quantity;
current.price += item.price;
return current;
} else {
return Object.assign( {}, item ); // shallow copy beware
}
}, null );
} );
}
PS I noticed in your input sample things like quantity and price were strings instead of numbers. I'm going to assume you know how to straighten those things out so the data has proper data types. This won't work if you have strings for those.

how to search nested objects and group according to a field

I have an array that contains nested objects, and i want to filter the objects according to a particular field. Items array contains an item object, that contains some particular field like name, id, price, and vendorid. I want to sort and filter the array according to the vendorid field. For example an array like :
var items=[{item:{name:"cap",
id:"5d767e1358ad1d0ca4894592",
price:50,
vendorid:"5d72d2a6d87c4628ba60e046"
},
}
{item:{name:"shorts",
price:100,
vendorid:"5d71c51f2092d318a1bf8f53"
}
},
{item:{name:"shoes",
price:90,
vendorid:"5d71c51f2092d318a1bf8f53"
}
}
{item:{name:"black hood",
price:120,
vendorid:"5d71c51f2092d318a1bf8f53"
}
}
]
I want to create an object that outputs this :
results = {"5d71c51f2092d318a1bf8f53":[{name:"shorts"
price:100,
vendorid:"5d71c51f2092d318a1bf8f53"},
{name:"shoes",
price:90,
vendorid:"5d71c51f2092d318a1bf8f53"},
{name:"black hood",
price:120,
vendorid:"5d71c51f2092d318a1bf8f53"}
],
"5d72d2a6d87c4628ba60e046":[{name:"cap",
id:"5d767e1358ad1d0ca4894592",
price:50,
vendorid:"5d72d2a6d87c4628ba60e046"
}
]
}
The results object format is {vendorid:[array containing objects with the same vendorid]}.
Thanks very much!!!
You can use reduce() method to do that.
var items = [{ item: { name: "cap", id: "5d767e1358ad1d0ca4894592", price: 50, vendorid: "5d72d2a6d87c4628ba60e046" } } ,{ item: { name: "shorts", price: 100, vendorid: "5d71c51f2092d318a1bf8f53" } }, { item: { name: "shoes", price: 90, vendorid: "5d71c51f2092d318a1bf8f53" } }, { item: { name: "black hood", price: 120, vendorid: "5d71c51f2092d318a1bf8f53" } } ];
let result = items.reduce((obj, currentValue) => {
if (!obj[currentValue.item.vendorid]) {
obj[currentValue.item.vendorid] = [];
}
obj[currentValue.item.vendorid].push({
...currentValue.item
});
return obj;
}, {});
const orderedResult = {};
// Sorting on vendorid.
Object.keys(result).sort().forEach(key => orderedResult[key] = result[key]);
console.log(orderedResult);
A note on ordering of object properties:
As of ECMAScript 2015 (ES6), object's own properties do have order
for some operations, but relying on it isn't a good idea. If order is
important, then better to use an array or something similar.

How to get JSON keys and add extra fields?

I'm trying to get the key of these json objects in order to create a new object with extra filed to create table headers in a React app. JSON data:
let example = [
{
id: 1,
city: 'New York',
},
{
id: 2,
city: 'Paris',
},
]
The function:
getKeys() {
return example.map((key) => {
return {
cityName: key, // gets the whole array
capital: false,
};
});
}
I tries Object.keys( example);, it returns integers; 0, 1.
How can I get the keys in this case? Thanks.
You are trying to map the keys for an array since example is an array. If the data are consistent throughout the array get the first element example[0] and do Object.keys().
So Object.keys(example[0])
There's no need to get the keys if you just want to add a property to the items in the array. I think there's a misunderstanding about .map, which gives you a single item/object in the array, not the keys.
Something like this perhaps?
let example = [{
id: 1,
city: 'New York',
}, {
id: 2,
city: 'Paris',
}];
const modifiedArray = function(arr) {
return arr.map(item => {
return {
id: item.id,
cityName: item.city,
capital: false,
};
})
}
const newArray = modifiedArray (example);
console.log(newArray )

How to create dynamic table headers from JSON in React?

I have a JSON array of objects, I want to create a dynamic table columns/headers based on it in React.
The data:
example = [
{
id: 0,
city: 'New York',
},
{
id: 1,
city: 'Paris',
},
]
I want to iterate through the array, get the key and add extra fields.
So far I have:
columns() {
return Object.keys(Example[0]).map((key) => {
return {
cityName: key,
capital: false,
};
});
}
I get the keys, but they are unordered (random) and the extra field is added to all the objects. I want to get each key to use it as table header (column name) and be able to change capital for each object.
How can I do that in React?
You can use Array.map for this.
example = [
{
id: 0,
city: 'New York',
},
{
id: 1,
city: 'Paris',
},
];
example.map((obj) => {
return {
CITY : obj.city,
ID : obj.id
// Do whatever with the objects
}
})
arr => arr && arr[0] ? object.keys(arr[0]) : [];
make sure all items in array have same keys

Categories

Resources