How to calculate average from nested values in an array using javascript? - javascript

I am trying to calculate the average duration for each stage. So in the array below - I should be able to get the average duration for 'test1', which would be 2.
jobs = [
{
"build_id": 1,
"stage_executions": [
{
"name": "test1"
"duration": 1,
},
{
"name": "test2"
"duration": 16408,
},
{
"name": "test3"
"duration": 16408,
},
]
},
{
"build_id": 2,
"stage_executions": [
{
"name": "test1"
"duration": 3,
},
{
"name": "test2"
"duration": 11408,
},
{
"name": "test3"
"duration": 2408,
},
]
}
]
My failed attempt:
avgDuration: function(jobs) {
let durationSum = 0
for (let item = 0; item < this.jobs.length; item++) {
for (let i = 0; i < this.jobs[item].stage.length; item++) {
durationSum += stage.duration
}
durationAverage = durationSum/this.jobs[item].stage.length
}
return durationAverage
What am I doing wrong? I'm not sure how to accomplish this since the duration is spread out between each job.
UPDATE:
This is return a single average for all stages rateher than per stage
<template>
<div class="stages">
<h3>
Average Duration
</h3>
<table>
<tbody>
<tr v-for="item in durations">
<td>
<b>{{ item.average}} {{ item.count }}</b>
// this returns only 1 average and 177 count instead of 10
<br />
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { calculateDuration } from "../../helpers/time.js";
import { liveDuration } from "../../helpers/time.js";
import moment from "moment";
export default {
name: "Stages",
data() {
return {
jobs: [],
durations: []
};
},
methods: {
avgDuration: function(jobs) {
var averageByName = {}; // looks like { 'name': { average: 111, count: 0 }}
for (var job of jobs) {
for(var stage of job.stage_execution) {
if (averageByName[stage.name] == null) { // we need a new object
averageByName[stage.name] = { average: 0, count: 0 };
}
// just name it so its easier to read
var averageObj = averageByName[stage.name];
// update count
averageObj.count += 1;
// Cumulative moving average
averageObj.average = averageObj.average + ( (stage.duration - averageObj.average) / averageObj.count );
console.log(averageObj.count)
}
}
return averageByName
},
},
created() {
this.JobExecEndpoint =
process.env.VUE_APP_TEST_URL +
"/api/v2/jobs/?limit=10";
fetch(this.JobExecEndpoint)
.then(response => response.json())
.then(body => {
for (let i = 0; i < body.length; i++) {
this.jobs.push({
name: body[i].job.name,
job: body[i].job,
stage_execution: body[i].stage_executions,
});
}
})
.then(() => {
this.$emit("loading", true);
})
.then(() => {
this.durations = this.avgDuration(this.jobs);
})
.catch(err => {
console.log("Error Fetching:", this.JobExecEndpoint, err);
return { failure: this.JobExecEndpoint, reason: err };
});
}
};
</script>

We can do this pretty simply and without overflow from having too many numbers by using a Cumulative moving average and a few loops.
Here is a line the relevant Wikipedia page on Moving Averages and the most relvant formula below.
I will not go into much detail with the above as there are a lot of documents describing this sort of thing. I will however say that the main reason to this over adding all the values together is that there is a far lower chance of overflow and that is why I am using it for this example.
Here is my solution with comments made in code.
var jobs = [ { "build_id": 1, "stage_executions": [ { "name": "test1", "duration": 1, }, { "name": "test2", "duration": 16408, }, { "name": "test3", "duration": 16408, }, ] }, { "build_id": 2, "stage_executions": [ { "name": "test1", "duration": 3, }, { "name": "test2", "duration": 11408, }, { "name": "test3", "duration": 2408, }, ] } ];
var averageByName = {}; // looks like { 'name': { average: 111, count: 0 }}
for (var job of jobs) {
for(var stage of job.stage_executions) {
if (averageByName[stage.name] == null) { // we need a new object
averageByName[stage.name] = { average: 0, count: 0 };
}
// just name it so its easier to read
var averageObj = averageByName[stage.name];
// update count
averageObj.count += 1;
// Cumulative moving average
averageObj.average = averageObj.average + ( (stage.duration - averageObj.average) / averageObj.count );
}
}
// print the averages
for(var name in averageByName) {
console.log(name, averageByName[name].average);
}
Let me know if you have any questions or if anything is unclear.

You could collect the values in an object for each index and map later only the averages.
var jobs = [{ build_id: 1, stage_executions: [{ name: "test1", duration: 1 }, { name: "test2", duration: 16408 }, { name: "test3", duration: 16408 }] }, { build_id: 2, stage_executions: [{ name: "test1", duration: 3 }, { name: "test2", duration: 11408 }, { name: "test3", duration: 2408 }] }],
averages = jobs
.reduce((r, { stage_executions }) => {
stage_executions.forEach(({ duration }, i) => {
r[i] = r[i] || { sum: 0, count: 0 };
r[i].sum += duration;
r[i].avg = r[i].sum / ++r[i].count;
});
return r;
}, []);
console.log(averages.map(({ avg }) => avg));
console.log(averages);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I've used Array.prototype.flatMap to flatten the jobs array into an array of {name:string,duration:number} object. Also, to make more solution a bit more dynamic the function takes in a field argument which returns the average for that specific field.
const jobs = [
{
"build_id": 1,
"stage_executions": [
{
"name": "test1",
"duration": 1,
},
{
"name": "test2",
"duration": 16408,
},
{
"name": "test3",
"duration": 16408,
},
]
},
{
"build_id": 2,
"stage_executions": [
{
"name": "test1",
"duration": 3,
},
{
"name": "test2",
"duration": 11408,
},
{
"name": "test3",
"duration": 2408,
},
]
}
];
const caller = function(jobs, field) {
const filtered = jobs
.flatMap((item) => item.stage_executions)
.filter(item => {
return item.name === field;
})
const total = filtered.reduce((prev, curr) => {
return prev + curr.duration;
}, 0)
return total / filtered.length;
}
console.log(caller(jobs, 'test1'))
console.log(caller(jobs, 'test2'))
console.log(caller(jobs, 'test3'))
In case you get the error flatMap is not a function. You can add this code snippet in your polyfill or at the top of your js file.
Array.prototype.flatMap = function(lambda) {
return Array.prototype.concat.apply([], this.map(lambda));
};
PS: for demostration, I obtained the flatMap implementation from here

Related

change data in nested array

I am trying to use an javascript algorithm to convert the data from products mode to reward mode, please help me :
var products = [{
id: "65864",name_fa:"پک دفتر 40 برگ وزيري شوميز کلاسيک 40 ",
details:[{master: 5,slave: 0,slave2: 0},{master: 11,slave: 0,slave2: 0}]
},{
id: 67532,name_fa: "100-بازی لونا",
details:[{master: 0,slave: 5,slave2: 0}]
}]
TO :
reward: [
{products: [
{
id: "65864",
name_fa:"پک دفتر 40 برگ وزيري شوميز کلاسيک 40" ,
"master": "5",
"slave": "0",
"slave2": "0"
},
{
"id": "67532",
"name_fa":"100-بازی لونا" ,
"master": "0",
"slave": "5",
"slave2": "0"
}
],
},
{"products": [
{
"id": "65864",
"name_fa":"پک دفتر 40 برگ وزيري شوميز کلاسيک 40" ,
"master": "11",
"slave": "0",
"slave2": "0"
},
{
"id": "67532",
"name_fa":"100-بازی لونا" ,
"master": "0",
"slave": "5",
"slave2": "0"
}
],
}
]
example:
[1,2],[3]
to
[1,3],[2,3]
I am trying to use an javascript algorithm to convert the data from products mode to reward mode, please help me
It's called cartesian product. I'm reusing a function and apply it on 2 arrays. The products, and the details. Then I combine those arrays (should be same length) into the required result.
// from: https://stackoverflow.com/a/36234242/3807365
function cartesianProduct(arr) {
return arr.reduce(function(a, b) {
return a.map(function(x) {
return b.map(function(y) {
return x.concat([y]);
})
}).reduce(function(a, b) {
return a.concat(b)
}, [])
}, [
[]
])
}
var products = [{
id: "65864",
name_fa: "پک دفتر 40 برگ وزيري شوميز کلاسيک 40 ",
details: [{
master: 5,
slave: 0,
slave2: 0
}, {
master: 11,
slave: 0,
slave2: 0
}]
}, {
id: 67532,
name_fa: "100-بازی لونا",
details: [{
master: 0,
slave: 5,
slave2: 0
}]
}];
var input = products.reduce(function(agg, item) {
agg.push(item.details);
return agg;
}, []);
var a = cartesianProduct(input);
// same for the id and names
var input2 = products.reduce(function(agg, item) {
var ids = []
item.details.forEach(function(_) {
ids.push({
id: item.id,
name_fa: item.name_fa
})
})
agg.push(ids);
return agg;
}, []);
var b = cartesianProduct(input2);
//console.log(JSON.stringify(a, null, 2));
//console.log(b)
var reward = [];
for (var i = 0; i < a.length; i++) {
var newGroup = {
products: []
}
for (var j = 0; j < a[i].length; j++) {
var newMan = {}
newGroup.products.push({
...b[i][j],
...a[i][j]
})
}
reward.push(newGroup)
}
console.log(reward)
.as-console-wrapper {
max-height: 100% !important
}

Group array of objects with a specific key value pushed first

Given the following Array of Objects:
[
{
"teamFK": 8650,
"code": "yellow_cards",
"typeId": 554,
"value": "5",
"side": "home"
},
{
"teamFK": 8650,
"code": "goals",
"typeId": 554,
"value": "1",
"side": "home"
},
{
"teamFK": 8990,
"code": "yellow_cards",
"typeId": 555,
"value": "2",
"side": "away"
},
{
"teamFK": 8990,
"code": "goals",
"typeId": 555,
"value": "0",
"side": "away"
}
]
I would like to group this data by code and get this result:
{
"stats": [
{
"name": "yellow_cards",
"stats": ["5","2"]
},
{
"name": "goals",
"stats": ["2","0"]
}
]
}
What I've done is the following which works but I want to make sure that the alway the stat with "side":"home" always pushed first into the array "stats": []:
const groupedStats = Object.entries(
query.reduce((acc, { typeId, value, code, side }) => {
if (!acc[code]) {
acc[code] = [];
}
acc[code].push(value);
return acc;
}, {}),
).map(([name, stats]) => ({ name, stats }));
My approach is sort it first by side using Array.sort() and then looping through the objects and adding it to stats
i created a const match to find if there is a match already so i dont have to add the name and value again basically if its not a match i'll add it to the stats array and if its a match then i'll just update the current index
const objs = [
{
teamFK: 8650,
code: "yellow_cards",
typeId: 554,
value: "5",
side: "home",
},
{
teamFK: 8650,
code: "goals",
typeId: 554,
value: "1",
side: "away",
},
{
teamFK: 8990,
code: "yellow_cards",
typeId: 555,
value: "2",
side: "away",
},
{
teamFK: 8990,
code: "goals",
typeId: 555,
value: "0",
side: "home",
},
];
let stats = [];
const transformedObj = objs
.sort((a, b) => {
if (a.side > b.side) {
return -1;
}
if (a.side < b.side) {
return 1;
}
return 0;
})
.forEach((obj) => {
const match = stats.find((stat) => stat.name === obj.code);
const statsIndex = stats.findIndex((stat) => stat.name === obj.code);
if (!match) {
stats = [...stats, { name: obj.code, value: [obj.value] }];
} else {
stats[statsIndex] = {
name: stats[statsIndex].name,
value: [...stats[statsIndex].value, obj.value],
};
}
});
console.log(stats);
You can sort array and use key grouping approach:
const data = [{"teamFK": 8650,"code": "yellow_cards","typeId": 554,"value": "5","side": "home"},{"teamFK": 8650,"code": "goals","typeId": 554,"value": "1","side": "home"},{"teamFK": 8990,"code": "yellow_cards","typeId": 555,"value": "2","side": "away"},{"teamFK": 8990,"code": "goals","typeId": 555,"value": "0","side": "away"}];
const groups = data
.sort(({ side: a }, { side: b }) => b.localeCompare(a))
.reduce((acc, { code, value }) => {
acc[code] ??= { name: code, stats: [] };
acc[code]['stats'].push(value);
return acc;
}, {});
const result = { stats: Object.values(groups) };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }

How can I sum values inside reduce with multi condition?

I want to sum up all of data base on two condition in side my reduce function.
Let's say I have data as following:
const data = [
{
"id": 1,
"option": BP,
"result": 'win',
"amount": 50
},
{
"id": 3,
"option": BP,
"result": 'win',
"amount": 20
},
{
"id": 5,
"option":VN,
"result": 'win',
"amount": 50
},
{
"id": 5,
"option":GB,
"result": 'loss',
"amount": 40
}
];
Here is my code:
data.reduce((newValueBetting, modelBetting) => {
if (
modelBetting.option === 'VN'
&& modelBetting.result === 'win'
) {
newValueBetting += modelBetting.amount;
}
return newValueBetting;
}, 0);
Regarding to this code. it will sum when my data is matches with condition. But, if I want to sum up option === 'BP' && result === 'win'. So, I don't want to write code again. Any idea? How can I make my reduce run only one time and get to this object:
{
TotalBPWin: 70,
TotalVN: 50,
TotalGBLoss: 40
}
While using reduce pass an object with all 3 key TotalBPWin, TotalVN, TotalGBLoss with initial value as 0. Then conditionally add them together.
const data = [{
id: 1,
option: "BP",
result: "win",
amount: 50,
},
{
id: 3,
option: "BP",
result: "win",
amount: 20,
},
{
id: 5,
option: "VN",
result: "win",
amount: 50,
},
{
id: 5,
option: "GB",
result: "loss",
amount: 40,
},
];
const accumulator = {
TotalBPWin: 0,
TotalVN: 0,
TotalGBLoss: 0,
};
const result = data.reduce((newValueBetting, { option, result, amount }) => {
if (option === "VN" && result === "win") {
newValueBetting["TotalVN"] += amount;
} else if (option === "BP" && result === "win") {
newValueBetting["TotalBPWin"] += amount;
} else if (option === "GB" && result === "loss") {
newValueBetting["TotalGBLoss"] += amount;
}
return newValueBetting;
}, accumulator);
console.log(result);
The idea is to use object in reduce rather than 0. The following is the simple implementation, you will probably need to refine the condition in the reduce for summation.
const data = [
{
"id": 1,
"option": 'BP',
"result": 'win',
"amount": 50
},
{
"id": 3,
"option": 'BP',
"result": 'win',
"amount": 20
},
{
"id": 5,
"option":'VN',
"result": 'win',
"amount": 50
},
{
"id": 5,
"option":'GB',
"result": 'loss',
"amount": 40
}
];
let result = {
'VN':0,
'GB':0,
'BP':0
};
data.reduce((acc,item) => {
result[item.option] += item.amount
return acc;
}, result);
console.log(result)
The following reduce will get you a sum of counts for each option. Importantly, if any option has zero wins, then there won't be an associated sum for it (See the log output).
const data = [{id:1,option:"BP",result:"win",amount:50},{id:3,option:"BP",result:"win",amount:20},{id:5,option:"VN",result:"win",amount:50},{id:5,option:"GB",result:"loss",amount:40}];
const result = data.reduce((all, el) => {
if (el.result === "win") {
all[el.option] = (all[el.option] || 0) + el.amount;
}
return all;
}, {});
console.log(result.BP);
console.log(result.VN);
console.log(result.GB);
You just need a simple loop for this and no need for if() conditionals
const data=[{id:1,option:"BP",result:"win",amount:50},{id:3,option:"BP",result:"win",amount:20},{id:5,option:"VN",result:"win",amount:50},{id:5,option:"GB",result:"loss",amount:40}];
const res= {};
data.forEach(o=>{
const k = 'Total' + o.option + o.result
res[k] = (res[k] || 0) + o.amount
});
console.log(res)

Get property of a grouped result from reduce in javascript

In grouped result I need the property of vendor and store in new array. but the give me some error. the error is Error: words is not defined.
how can I get vendor property from grouped list?
it is about to get result and store in new property.
const cart = {
"_id": 2,
"owner": 7,
"products": [{
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b2"
},
"product": 1,
"vendor": 1,
"quantity": 2
}, {
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b3"
},
"product": 2,
"vendor": 1,
"quantity": 1
}, {
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b4"
},
"product": 4,
"vendor": 2,
"quantity": 1
}],
"createdAt": {
"$date": "2020-06-21T06:46:40.111Z"
},
"updatedAt": {
"$date": "2020-07-09T11:04:04.459Z"
},
"__v": 0,
"totalPrice": 265
}
const product = cart.products;
var grouped = product.reduce((dictionary, p) => {
dictionary[p.vendor] = dictionary[p.vendor] || [];
dictionary[p.vendor].push(p);
return dictionary;
}, {})
for (const p in grouped) {
console.log(grouped[p].vendor)
}
const cart = {
_id: 2,
owner: 7,
products: [
{
_id: {
$oid: "5f06f9a4b8b878050fbc54b2",
},
product: 1,
vendor: 1,
quantity: 2,
},
{
_id: {
$oid: "5f06f9a4b8b878050fbc54b3",
},
product: 2,
vendor: 1,
quantity: 1,
},
{
_id: {
$oid: "5f06f9a4b8b878050fbc54b4",
},
product: 4,
vendor: 2,
quantity: 1,
},
],
createdAt: {
$date: "2020-06-21T06:46:40.111Z",
},
updatedAt: {
$date: "2020-07-09T11:04:04.459Z",
},
__v: 0,
totalPrice: 265,
};
// const result = words.filter((word) => word.length > 6); // useless line, you do not have variable 'words'
const f = cart.products.filter((p) => p.vendor == 1);
const products = cart.products; //better variable naming
var grouped = products.reduce((dictionary, p) => {
dictionary[p.vendor] = dictionary[p.vendor] || [];
dictionary[p.vendor].push(p);
return dictionary;
}, {});
for (const p in grouped) {
console.log(grouped[p]); //is array
}
To fix this code just delete the line where you use variable words coz you didn't declare such.
To get vendor value:
grouped[p] is an array. It doesn't have a property vendor. But you can get it with:
for (const p in grouped) {
console.log(grouped[p][0].vendor);
}
or get an array of them:
let vendors = Object.getOwnPropertyNames(grouped);
Aside from the 2 lines of code which do nothing, I think you're trying to get the id of the vendor for each group - in which case this is just p in your code at the bottom which logs:
const cart = {"_id":2,"owner":7,"products":[{"_id":{"$oid":"5f06f9a4b8b878050fbc54b2"},"product":1,"vendor":1,"quantity":2},{"_id":{"$oid":"5f06f9a4b8b878050fbc54b3"},"product":2,"vendor":1,"quantity":1},{"_id":{"$oid":"5f06f9a4b8b878050fbc54b4"},"product":4,"vendor":2,"quantity":1}],"createdAt":{"$date":"2020-06-21T06:46:40.111Z"},"updatedAt":{"$date":"2020-07-09T11:04:04.459Z"},"__v":0,"totalPrice":265}
//const result = words.filter(word => word.length > 6);
//const f = cart.products.filter(p => p.vendor == 1);
const product = cart.products;
var grouped = product.reduce((dictionary, p) => {
dictionary[p.vendor] = dictionary[p.vendor] || [];
dictionary[p.vendor].push(p);
return dictionary;
}, {})
let vendor;
for (const p in grouped) {
console.log("vendor=", p, " count of items=", grouped[p].length)
}
I think this will give you the result you are looking for:
let f = cart.products.map( p => p.vendor);
let newArray = f.filter((vendor,index,arr)=>vendor!==arr[index+1]);
newArray.forEach(element => {
console.log(element);
});
You have some extraneous code in your script.
const result = words.filter(word => word.length > 6);
On line 36 you write const result = words.filter(word => word.length > 6); but words is not defined anywhere in your code and that is what generates the error.
For what concerns what you want to achieve, I am not entirely sure I understood it but, if I did, you can solve your issue like this:
const cart = {
"_id": 2,
"owner": 7,
"products": [{
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b2"
},
"product": 1,
"vendor": 1,
"quantity": 2
}, {
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b3"
},
"product": 2,
"vendor": 1,
"quantity": 1
}, {
"_id": {
"$oid": "5f06f9a4b8b878050fbc54b4"
},
"product": 4,
"vendor": 2,
"quantity": 1
}],
"createdAt": {
"$date": "2020-06-21T06:46:40.111Z"
},
"updatedAt": {
"$date": "2020-07-09T11:04:04.459Z"
},
"__v": 0,
"totalPrice": 265
}
const products = cart.products;
const vendors = products
.map(product => product.vendor)
.reduce((vendors, vendor) => {
if (vendors.indexOf(vendor) < 0) {
vendors.push(vendor);
}
return vendors;
}, []);
const productsByVendor = products.reduce((dictionary, p) => {
dictionary[p.vendor] = dictionary[p.vendor] || [];
dictionary[p.vendor].push(p);
return dictionary;
}, {});
console.log('Products grouped by vendor:\n', productsByVendor);
// in 'productsByVendor' the vendors are the keys of your object
console.log('Vendors:', Object.keys(productsByVendor));
/* if you want to retrieve the vendor of a specific product from 'productsByVendor'
* Assumptions:
* 1. cart.products[n].product is assumed to be a unique id (if that is not the case, you can use cart.products[n]._id instead)
* 2. I am assuming that each product can be sold by only one vendor; if a product can be sold by more than one vendor you'll have to adjust a bit the function
*/
getVendorIdFromGroupedProducts = (productId) => {
for (let key of Object.keys(productsByVendor)) {
for (let prod of productsByVendor[key]) {
if (prod.product === productId) {
return prod.vendor
}
}
}
return 'The product does not exist'
};
console.log('Vendor of product 1 is:', getVendorIdFromGroupedProducts(1));
console.log('Vendor of product 2 is:', getVendorIdFromGroupedProducts(2));
console.log('Vendor of product 3 is:', getVendorIdFromGroupedProducts(3));
console.log('Vendor of product 4 is:', getVendorIdFromGroupedProducts(4));

javascript - reorder array of objects depending on property

I am building a select dropdown input for a webpage. I want to make a 'popular' options group which appears at the top of the dropdown.
I am working with data in the following structure.
I need to find a way to reorder the items inside the people array based on their name.
For example moving:
pogo-stick from toys[2] -> toys[0]
cards from toys[3] to toys [2]
I will have an array of popular toys such as:
popularToys: [
"cards", "pogo-stick"
]
How can I iterate through the array of objects and move them in to the new order?
Data:
{
"toys": [
{
"name": "car",
"price": "10"
},
{
"name": "duck",
"price": "25"
},
{
"name": "pogo-stick",
"price": "60"
},
{
"name": "cards",
"price": "5"
}
]
}
Use forEach() loop where you can find the index of the toy object and swap:
var popularToys = [
"cards", "pogo-stick"
]
var data = {
"toys": [
{
"name": "car",
"price": "10"
},
{
"name": "duck",
"price": "25"
},
{
"name": "pogo-stick",
"price": "60"
},
{
"name": "cards",
"price": "5"
}
]
};
popularToys.forEach(function(toy, index){
var toyObjIndex = data.toys.findIndex(x => x.name==toy);
//swap
var tempObj = data.toys[toyObjIndex];
data.toys[toyObjIndex] = data.toys[index];
data.toys[index] = tempObj;
});
console.log(data);
Using a combination of map and filter we are able to split the required logic into to methods (Maybe more readable)
Popular() returns a filtered Array of any of the toy items that have a name property that corresponds with the current name in the iteration of popular
Rest() returns a filtered Array of toys where the name property of the toy in the iteration does not exist in the Array of String in popular
const toys = [
{
name: 'car',
price: '10'
},
{
name: 'exception',
price: '999999'
},
{
name: 'duck',
price: '25'
},
{
name: 'pogo-stick',
price: '60'
},
{
name: 'cards',
price: '5'
},
{
name: 'another !exception',
price: '100000'
},
{
name: 'pogo-stick',
price: 'A MILLION POUNDS'
},
{
name: 'duck',
price: '100'
}
]
const popular = [
'cards',
'pogo-stick',
'car',
'duck'
]
const Popular = () => {
return [].concat(...popular.map(n => toys.filter(({name}) => name === n)))
}
const Rest = () => toys.filter(({name}) => popular.indexOf(name) === -1)
let ordered = [].concat(...Popular(), ...Rest())
console.log(ordered)
You could use a custom sort function
var popularToys = [
"cards", "pogo-stick"
]
var data = {
"toys": [
{
"name": "car",
"price": "10"
},
{
"name": "duck",
"price": "25"
},
{
"name": "pogo-stick",
"price": "60"
},
{
"name": "cards",
"price": "5"
}
]
};
function popularFirst(a, b) {
var aIsPopular = popularToys.indexOf(a.name) > -1;
var bIsPopular = popularToys.indexOf(b.name) > -1;
if (aIsPopular) {
// b could be popular or not popular, a still comes first
return -1;
} else if (bIsPopular) {
// a isnt popular but b is, change the order
return 1;
} else {
// no change
return 0;
}
}
console.log(data.toys.sort(popularFirst));
function compare(a,b) {
if (a.name < b.name)
return -1;
if (a.name > b.name)
return 1;
return 0;
}
toys.sort(compare);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Categories