I need to amend the amount to add £ before the number and change it to two decimals i.e. £9.00
const data = [
{
title: 'Todo',
amount: 9.99,
},
{
title: 'In-Progress',
amount: 4,
},
{
title: 'Completed',
amount: 10,
},
{
title: 'Short',
amount: 15.48,
},
];
I can't work out how?
You could do that, or you could use the Intl.NumberFormat to change it to currency on-the-fly. That way you get to keep your data neutral, and let the browser/JS handle the transformation only when it's needed.
const data=[{title:"Todo",amount:9.99},{title:"In-Progress",amount:4},{title:"Completed",amount:10},{title:"Short",amount:15.48}];
const style = { style: 'currency', currency: 'GBP' };
for (const obj of data) {
const currency = new Intl.NumberFormat('en-GB', style).format(obj.amount);
console.log(currency);
}
If you still want to change the data this method is still preferable. map over the data, destructure the amount from the object, and return a new object with the transformed amount.
const data=[{title:"Todo",amount:9.99},{title:"In-Progress",amount:4},{title:"Completed",amount:10},{title:"Short",amount:15.48}];
const style = { style: 'currency', currency: 'GBP' };
function toGBP(amount) {
return new Intl.NumberFormat('en-GB', style).format(amount);
}
const out = data.map(obj => {
const { amount, ...rest } = obj;
return { ...rest, amount: toGBP(amount) };
});
console.log(out);
Additional documentation
Rest parameters
Spread syntax
Just map through it and use .toFixed(2) for the decimal.
const data = [
{
title: 'Todo',
amount: 9.99,
},
{
title: 'In-Progress',
amount: 4,
},
{
title: 'Completed',
amount: 10,
},
{
title: 'Short',
amount: 15.48,
},
];
const mapped = data.map((n) => { return {title: n.title, amount: `£${n.amount.toFixed(2)}`}});
console.log(mapped);
You can use Number#toFixed(2) and Array#map() methods as follows:
const
data = [ { title: 'Todo', amount: 9.99, }, { title: 'In-Progress', amount: 4, }, { title: 'Completed', amount: 10, }, { title: 'Short', amount: 15.48 } ],
out = data.map(({title,amount}) => ({title,amount:`£${amount.toFixed(2)}`}));
console.log( out );
Related
I thought I understood how to loop through a dictionary, but my loop is wrong. I try to access the name of each sub item but my code does not work.
Here is what I did:
list = [
{
title: 'Groceries',
items: [
{
id: 4,
title: 'Food',
cost: 540 ,
},
{
id: 5,
title: 'Hygiene',
cost: 235,
},
{
id: 6,
title: 'Other',
cost: 20,
},
],
}];
function calculateCost(){
let total = 0;
Object.keys(list).forEach((k) => { for (i in k.items) { total += i.data; } });
console.log(total);
return total;
}
Your list is an array includes 1 object and this object has two properties title and items the items here is an array of objects each one of these objects has property cost so to calculate the total cost you need to loop through items array, here is how you do it:
let list = [
{
title: 'Groceries',
items: [
{
id: 4,
title: 'Food',
cost: 540 ,
},
{
id: 5,
title: 'Hygiene',
cost: 235,
},
{
id: 6,
title: 'Other',
cost: 20,
},
],
}];
function calculateCost(){
let total = 0;
list[0].items.forEach(el => {
total += el.cost;
})
console.log(total)
return total;
}
calculateCost();
Your list is an Array, not an Object.
Instead of Object.keys() use Array.prototype.reduce:
const calculateCost = (arr) => arr.reduce((tot, ob) =>
ob.items.reduce((sum, item) => sum + item.cost, tot), 0);
const list = [
{
title: 'Groceries',
items: [
{id: 4, title: 'Food', cost: 10},
{id: 5, title: 'Hygiene', cost: 20},
{id: 6, title: 'Other', cost: 30}
]
}, {
title: 'Other',
items: [
{id: 8, title: 'Scuba gear', cost: 39}
],
}
];
console.log(calculateCost(list)); // 99
Expanding on #Roko's and #mmh4all's answers, the following code adds several verification statements to handle cases where a deeply nested property in your data is not what you expect it to be.
const calculateCost = (orders) => {
let listOfCosts = [];
// For each 'order' object in the 'orders' array,
// add the value of the 'cost' property of each item
// in the order to 'listOfCosts' array.
orders.forEach(order => {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray(order.items)) { return; }
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloat
const orderCostArr = order.items.map(item =>
isNaN(item.cost) ? 0 : parseFloat(item.cost, 10));
if (orderCostArr.length === 0) { return; }
// Concatenate 'orderCostArr' to the 'listOfCosts' array
//listOfCosts = listOfCosts.concat(orderCostArry);
// Alternate approach is to use the spread syntax (...) to
// push the items in the array returned by 'order.items.map()'
// into the 'listOfCosts' array.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
listOfCosts.push(...orderCostArr);
});
// Use the 'reduce' method on the 'listOfCosts' array
// to get the total cost.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
const totalCost = listOfCosts.reduce(
(accumulator, currentValue) => accumulator + currentValue, 0);
return totalCost;
};
const list = [
{
title: 'Groceries',
items: [
{ id: 4, title: 'Food', cost: 10 },
{ id: 3, title: 'Baked goods', cost: 20 },
{ id: 5, title: 'Hygiene', cost: 0 },
{ id: 6, title: 'Other' }
]
}, {
title: 'Gear',
items: {},
}, {
title: 'Accessories',
items: [],
}, {
title: 'Bags',
}, {
title: 'Other',
items: [
{ id: 10, title: 'Scuba gear', cost: "5" },
{ id: 8, title: 'Scuba gear', cost: "err" },
{ id: 9, title: 'Scuba gear', cost: 59 }
],
}
];
console.log(calculateCost(list)); // 94
Need to convert Record Type in Typescript/Javascript to Array with specific property
const store: Record<ProductID, ProductObject> = {
'france': productObject:{
present: 'in_stock',
amount: 23,
},
'uk': productObject:{
present: 'in_stock',
amount: 20,
},
'japan': productObject:{
present: 'no_stock',
amount: 0,
},
}
Output: Creating New Array. Adding new key as 'country' & take only 'amount' property from store Record type.
const newArrayFromRecord = [
{country: 'france', amount: 23},
{country: 'uk', amount: 20}
{country: 'japan', amount: 0}
]
I have tried with Object.entries() and then pushing in Array. But all require unnecessary code. Is there any efficient way to do..
This is one possible way to achieve the objective:
Object.entries(store).map(([k, v]) => ({
country: k,
amount: v.amount
}))
Code Snippet using JS:
const store = {
'france': {
present: 'in_stock',
amount: 23,
},
'uk': {
present: 'in_stock',
amount: 20,
},
'japan': {
present: 'no_stock',
amount: 0,
},
};
console.log(
'result: ',
Object.entries(store).map(([k, v]) => ({
country: k,
amount: v.amount
}))
);
And, here's a TypeScript Playground link.
You could just loop over the store object using a for in loop.
Or mapping it with Object.keys.
Aside from that I don't think there is really a more "efficient" solution.
const store = {
france: {
present: "in_stock",
amount: 23,
},
uk: {
present: "in_stock",
amount: 20,
},
japan: {
present: "no_stock",
amount: 0,
},
};
const result = [];
for (const country in store) {
result.push({ country, amount: store[country].amount });
}
const result_2 = Object.keys(store).map((country) => ({
country,
amount: store[country].amount,
}));
console.log(result);
console.log(result_2);
Using Object.entries and destructuring
const data = {
'france': {
present: 'in_stock',
amount: 23,
},
'uk': {
present: 'in_stock',
amount: 20,
},
'japan': {
present: 'no_stock',
amount: 0,
},
};
const res = Object.entries(data).map(([country, { amount }]) => ({
country,
amount,
}));
console.log(res);
I have the following code with the following arrays. I want to loop through both of them and pull out some data, and put them inside a final array. I am able to do that, but the contents are duplicated. I tried reading about reduce but don't quite understand it, and am not sure if it's the right solution. I have also setup a jsfiddle
https://jsfiddle.net/anders_kitson/Lcqn6fgd/
var lineItems = [{
id: 'li_1HyhAZHk5l44uIELgsMWqHqB',
object: 'item',
amount_subtotal: 7500,
amount_total: 7500,
currency: 'cad',
description: 'The Spencer',
price: [Object],
quantity: 1
},
{
id: 'li_1HyhAZHk5l44uIELeNUsiZPu',
object: 'item',
amount_subtotal: 7500,
amount_total: 7500,
currency: 'cad',
description: 'The Gertie',
price: [Object],
quantity: 1
}
]
var arr = [{
id: 'prod_IS1wY1JvSv2CJg',
object: 'product',
active: true,
attributes: [],
created: 1606248785,
description: 'Shelf Set',
images: [
'https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq'
],
livemode: false,
metadata: {},
name: 'The Spencer',
statement_descriptor: null,
type: 'service',
unit_label: null,
updated: 1606248785
},
{
id: 'prod_IS299dMnC13Ezo',
object: 'product',
active: true,
attributes: [],
created: 1606249543,
description: 'Shelf Set',
images: [
'https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe'
],
livemode: false,
metadata: {},
name: 'The Gertie',
statement_descriptor: null,
type: 'service',
unit_label: null,
updated: 1606249543
}
];
let productArr = [];
arr.map((item) => {
lineItems.map((line) => {
productArr.push({
image: item.images[0],
name: item.name,
price: line.amount_total,
});
});
});
console.log(productArr);
This is the output I get where you can see the array repeats the values, and I know I have coded it this way I just don't know how to fix it.
[{
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}]
To Be more clear this is the output that I want
[{
image: "https://files.stripe.com/links/fl_test_raNEqk9ZhzX3WdQsnvXX4gFq",
name: "The Spencer",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
},
]
I have tried the suggestion in the comments with the following
let b
arr.map((item) => {
b = lineItems.map((line) => {
return {
image: item.images[0],
name: item.name,
price: line.amount_total,
};
});
});
but it returns the same ones twice
[{
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}, {
image: "https://files.stripe.com/links/fl_test_QPbrP76uNn4QadgcUwUnkmbe",
name: "The Gertie",
price: 7500
}]
Although not expressed directly in your question, it seems you're looking to do a join in javascript. The only things I see relating the two are 'name' in products and 'description' in the line items. So do a loop join on that.
Here's some sample code using your example but stripped down only to what's relevant:
var lineItems = [
{ amount_total: 7500, description: 'The Spencer' },
{ amount_total: 7500, description: 'The Gertie' }
]
var arr = [
{ images: ['Spencer Image 1'], name: 'The Spencer' },
{ images: ['Gertie Image 1'], name: 'The Gertie' }
]
let joined = arr
.flatMap(a => lineItems.map(li => ({a, li})))
.filter(obj => obj.a.name == obj.li.description)
.map(obj => ({
image: obj.a.images[0],
name: obj.a.name,
price: obj.li.amount_total
}));
console.log(joined);
Being a loop join, it may not be that efficient. To do a hash join is a little more involved. You can look through the source code of my developing project
fluent-data, or it might even be useful to you to use it directly if you can follow the documentation.
You can use a single map call and reference your second lineItems array either by index, if you know that the two arrays are the same length and order
const output = arr.map((o, i) => ({
name: o.name,
image: o.images[0],
price: lineItems[i].amount_total}
));
or by using find() to retrieve the relevant object.
const outputUsingFind = arr.map(o => {
const lineItem = lineItems.find(item => item.description === o.name);
// ** add lineItem valid check here **
return {
name: o.name,
image: o.images[0],
price: lineItem.amount_total};
});
var lineItems = [{amount_subtotal: 7500,amount_total: 700,description: 'The Spencer',},{amount_subtotal: 7500,amount_total: 500,description: 'The Gertie',}];
var arr = [{images: ['spencer image'],name: 'The Spencer',},{images: ['gertie image'],name: 'The Gertie'}];
// since your arrays are ordered the same you can access the second object using
// the index passed from map.
const output = arr.map((o, i) => ({
name: o.name,
image: o.images[0],
price: lineItems[i].amount_total}
));
console.log(output);
// if the two arrays are not in the same order you can use find() to retrieve
// the second object by property (you'll need to check
const outputUsingFind = arr.map(o => {
const lineItem = lineItems.find(item => item.description === o.name);
// ** add lineItem valid check here **
return {
name: o.name,
image: o.images[0],
price: lineItem.amount_total};
});
console.log(outputUsingFind);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Apologies for the potentially silly question - I'm fairly new to coding/JavaScript.
I am using Plaid's sandbox environment to pull in transactional data in a sandbox environment. Right now, I define the following as transactionData:
let transactionsData = [];
transactions.forEach(function(account) {
account.transactions.forEach(function(transaction) {
transactionsData.push({
account: account.accountName,
date: transaction.date,
category: transaction.category[0],
name: transaction.name,
amount: transaction.amount
});
});
});
I can successfully render the individual transactions row by row in a material table like so:
const transactionsColumns = [
{ title: "Account", field: "account" },
{ title: "Date", field: "date", type: "date", defaultSort: "desc" },
{ title: "Name", field: "name" },
{ title: "Amount", field: "amount", type: "numeric" },
{ title: "Category", field: "category" }
];
<MaterialTable
columns={transactionsColumns}
data={transactionsData}
}}
I know this has to be super simple, but all I want to do is sum the transactionsData and render that single summed value elsewhere on my page. If I write transactionsData.length I can receive the count of the transactions quite easily. I have tried the following somewhat similar syntax but have not found it to work:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
Any help would be much appreciated.
Here's total, using Array.prototype.reduce:
const transformed = [{"account":"Navy Federal Credit Union","date":"2020-01-01","category":"Travel","name":"United Airlines","amount":500},{"account":"Navy Federal Credit Union","date":"2019-12-30","category":"Travel","name":"Uber 072515 SF**POOL**","amount":6.33},{"account":"Navy Federal Credit Union","date":"2019-12-27","category":"Food and Drink","name":"Tectra Inc","amount":500}]
const unrounded = transformed.reduce(
(acc, { amount }) => acc + amount,
0
);
const roundCents = amount => Math.round(amount * 100) / 100;
const total = roundCents(unrounded);
console.log(total);
A plainer version of the above, with no destructuring:
const transformed = [{"account":"Navy Federal Credit Union","date":"2020-01-01","category":"Travel","name":"United Airlines","amount":500},{"account":"Navy Federal Credit Union","date":"2019-12-30","category":"Travel","name":"Uber 072515 SF**POOL**","amount":6.33},{"account":"Navy Federal Credit Union","date":"2019-12-27","category":"Food and Drink","name":"Tectra Inc","amount":500}]
const unrounded = transformed.reduce(
(acc, transaction) => acc + transaction.amount,
0
);
const roundCents = amount => Math.round(amount * 100) / 100;
const total = roundCents(unrounded);
console.log(total);
And here's how to transform transactionsData with Array.prototype.flatMap and Array.prototype.map, rather than forEach:
const transactionsData = [{ accountName: 'a1', transactions: [{ date: '2020', category: ['c1'], name: 'n1', amount: 100 }, { date: '2020', category: ['c2'], name: 'n2', amount: 100 }]}, { accountName: 'a2', transactions: [{ date: '2020', category: ['c3'], name: 'n3', amount: 100 }, { date: '2020', category: ['c4'], name: 'n4', amount: 100 }]}]
const transformed = transactionsData.flatMap(({ accountName, transactions }) =>
transactions.map(({ date, category, name, amount }) => ({
account: accountName,
date,
category: category[0],
name,
amount
})
)
);
console.log(transformed)
And again, a plainer version, without the destructuring:
const transactionsData = [{ accountName: 'a1', transactions: [{ date: '2020', category: ['c1'], name: 'n1', amount: 100 }, { date: '2020', category: ['c2'], name: 'n2', amount: 100 }]}, { accountName: 'a2', transactions: [{ date: '2020', category: ['c3'], name: 'n3', amount: 100 }, { date: '2020', category: ['c4'], name: 'n4', amount: 100 }]}]
const transformed = transactionsData.flatMap(account =>
account.transactions.map(transaction => ({
account: account.accountName,
date: transaction.date,
category: transaction.category[0],
name: transaction.name,
amount: transaction.amount
})
)
);
console.log(transformed)
Array.prototype.map is the correct method to use if you want to create a new array from an existing one, and Array.prototype.flatMap is the correct method to use if you need a flattened array and map would generate a nested one.
I am trying to make a new array from the data object that I have which looks like this:
const data= {
periods: [{
month: 'January',
types: [
{
name: 'sick leave',
difference: '14',
revisioned: '7000',
paid: '5000',
},
{
name: 'holiday',
difference: '12',
revisioned: '4000',
paid: '6000',
},
],
received: '3000',
taken: '2000',
result: '0',
},
{
month: 'February',
types: [
{
name: 'sick leave',
difference: '5',
revisioned: '100',
paid: '200',
},
{
name: 'holiday',
difference: '4',
revisioned: '300',
paid: '232',
},
],
received: '-2000',
taken: '2000',
result: '0',
}],
};
What I would like to do is, to take that object and take the properties types, received, taken and result and from each of these properties values create an array that would be a property of an object in a new array. The end result of the new array would look something like this:
[
{
name: 'sick_leave_difference',
result: ['14', '5'],
},
{
name: 'sick_leave_revisioned',
result: ['7000', '100'],
},
{
name: 'sick_leave_paid',
resultat: '[5000, 200]',
},
{
name: 'holiday_difference',
resultat: ['12', '4'],
},
{
name: 'holiday_revisioned',
result: ['4000', '300'],
},
{
name: 'holiday_paid',
result: '[6000, 232]',
},
{
name: 'received',
resultat: ['3000', '-2000'],
},
{
navn: 'taken',
result: ['2000', '2000'],
},
{
name: 'result',
result: ['0', '0'],
},
];
The problem is that the propery types contains an array and it is different is different from the other properties, so I am not sure how to achieve this and also in an elegant way?
Use Array.reduce() to extract and flatten the types array. Reduce the flattened array, and iterate the each object's entries with Array.forEach(). Create the result object if it doesn't exists, and add the results. Extract back to array using Object.values():
const data= {"periods":[{"month":"January","types":[{"name":"sick leave","difference":"14","revisioned":"7000","paid":"5000"},{"name":"holiday","difference":"12","revisioned":"4000","paid":"6000"}],"received":"3000","taken":"2000","result":"0"},{"month":"February","types":[{"name":"sick leave","difference":"5","revisioned":"100","paid":"200"},{"name":"holiday","difference":"4","revisioned":"300","paid":"232"}],"received":"-2000","taken":"2000","result":"0"}]};
const result = Object.values(data.periods
.reduce((r, { types }) => [...r, ...types], [])
.reduce((r, { name, ...props }) => {
Object.entries(props).forEach(([k, v]) => {
const navn = `${name} ${k}`.replace(' ', '-');
if(!r[navn]) r[navn] = { navn, result: [] };
r[navn].result.push(v);
});
return r;
}, {}));
console.log(result);