Ensure a random javascript object selection isn't selected twice - javascript

I want to store the random selection of a function in an array so that in future runs of the random function the property that was previously picked will not be selected. For example, I want it so if England is selected at random then, future runs of this function will omit England.
Javascript Object
var countryDataObj = {
England: { Title: "England", imageUrl: "", Total: 70 },
Spain: { Title: "Spain", imageUrl: "", Total: 57 },
Wales: { Title: "Wales", imageUrl: "", Total: 52 },
Germany: { Title: "Germany", imageUrl: "", Total: 16 },
Ireland: { Title: "Ireland", imageUrl: "", Total: 14 },
Russia: { Title: "Russia", imageUrl: "", Total: 19 },
Portugal: { Title: "Portugal", imageUrl: "", Total: 32 },
Wales: { Title: "Wales", imageUrl: "", Total: 52 },
France: { Title: "France", imageUrl: "", Total: 49 }
}
The current randomize function
function returnCountry(obj) {
var keys = Object.keys(obj);
return obj[keys[ keys.length * Math.random() << 0]];
};

There are many ways to do this, one would be an object-oriented approach.
class CountryPicker {
countries = [
{ Title: "England", imageUrl: "", Total: 70 },
{ Title: "Spain", imageUrl: "", Total: 57 },
{ Title: "Wales", imageUrl: "", Total: 52 },
{ Title: "Germany", imageUrl: "", Total: 16 },
{ Title: "Ireland", imageUrl: "", Total: 14 },
{ Title: "Russia", imageUrl: "", Total: 19 },
{ Title: "Portugal", imageUrl: "", Total: 32 },
{ Title: "Wales", imageUrl: "", Total: 52 },
{ Title: "France", imageUrl: "", Total: 49 }
];
randomCountry() {
if (this.countries.length == 0) throw new Error("None left");
const index = Math.floor(Math.random() * this.countries.length);
const result = this.countries[index];
this.countries.splice(index, 1);
return result;
}
}
const picker = new CountryPicker();
console.log(picker.randomCountry());
Playground

Related

Loop through JSON in dataLayer

I would like to get the summed value of all the arrays in the "products" object (price * quantity). The summed value should be returned in the return.
Do you have any ideas how to do that?
{
"event": "checkout",
"ecommerce": {
"checkout": {
"actionField": {
"step": 2,
"option": "Initiate checkout",
"action": "checkout"
},
"products": [
{
"id": "52",
"name": "Turystyczna kuchenka gazowa SMILE-KN-03/1K",
"price": 161.788618,
"brand": "",
"category": "kuchenki-elektryczne-i-gazowe",
"variant": "",
"quantity": "1"
},
{
"id": "36",
"name": "Kuchnia gazowa MPM-51-KGF-21",
"price": 641.463415,
"brand": "",
"category": "kuchnie-gazowe",
"variant": "",
"quantity": "1"
}
]
}
},
"gtm.uniqueEventId": 12
}
const g = {
event: 'checkout',
ecommerce: {
checkout: {
actionField: {
step: 2,
option: 'Initiate checkout',
action: 'checkout',
},
products: [
{
id: '52',
name: 'Turystyczna kuchenka gazowa SMILE-KN-03/1K',
price: 161.788618,
brand: '',
category: 'kuchenki-elektryczne-i-gazowe',
variant: '',
quantity: '1',
},
{
id: '36',
name: 'Kuchnia gazowa MPM-51-KGF-21',
price: 641.463415,
brand: '',
category: 'kuchnie-gazowe',
variant: '',
quantity: '1',
},
],
},
},
'gtm.uniqueEventId': 12,
};
const c = g.ecommerce.checkout.products.reduce((acc, curr) => {
acc += curr.price * curr.quantity;
return acc;
}, 0);
console.log(c)
guess you want something like this?

Find all values of a particular key in a array of objects or object of objets

I have an array of objects as below
let arr = [
{
name: "string 1",
details: [
{
id: 1,
values: [
{ date: "12-Mar", score: "15" },
{ date: "13-Mar", score: "16" },
{ date: "14-Mar", score: "17" },
{ date: "15-Mar", score: "18" },
],
},
],
},
{
name: "string 2",
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "16" },
{ date: "13-Mar", score: "17" },
{ date: "14-Mar", score: "18" },
{ date: "15-Mar", score: "19" },
],
},
],
},
{
name: "string 3",
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "21" },
{ date: "13-Mar", score: "22" },
{ date: "14-Mar", score: "23" },
{ date: "15-Mar", score: "24" },
],
},
],
},
];
I also have the same data as an object of objects as below
let obj = {
"string 1": {
details: [
{
id: 1,
values: [
{ date: "12-Mar", score: "15" },
{ date: "13-Mar", score: "16" },
{ date: "14-Mar", score: "17" },
{ date: "15-Mar", score: "18" },
],
},
],
},
"string 2": {
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "16" },
{ date: "13-Mar", score: "17" },
{ date: "14-Mar", score: "18" },
{ date: "15-Mar", score: "19" },
],
},
],
},
"string 3": {
details: [
{
id: "2",
values: [
{ date: "12-Mar", score: "21" },
{ date: "13-Mar", score: "22" },
{ date: "14-Mar", score: "23" },
{ date: "15-Mar", score: "24" },
],
},
],
},
};
I want to find all the dates & all the scores as an array.
For the array of ojects, with the help of answer here (How to find all values of a specific key in an array of nested objects?), I was able to get the result with the code below.
Since I did not want the dates to be repeated, I created a Set
dates = new Set(getValue(arr, "date"))
However, for the object of objects, I am not able to get the results. How do I go about it.
Also, I have the option to get my data as an array of objects or an object of objects. Since I have to perform a lot of manipulation/analysis (I will be using this with D3 library t build charts), which is the better format? Can anyone guide? Thanks.
You could use a recursive approach (as in the referenced answer) to pick all properties for a given key. One can also add a unique parameter, if this is set to true we'll create a Set from the properties to ensure we don't return any duplicates:
let arr = [ { name: "string 1", details: [ { id: 1, values: [ { date: "12-Mar", score: "15" }, { date: "13-Mar", score: "16" }, { date: "14-Mar", score: "17" }, { date: "15-Mar", score: "18" }, ], }, ], }, { name: "string 2", details: [ { id: 2, values: [ { date: "12-Mar", score: "16" }, { date: "13-Mar", score: "17" }, { date: "14-Mar", score: "18" }, { date: "15-Mar", score: "19" }, ], }, ], }, { name: "string 3", details: [ { id: 2, values: [ { date: "12-Mar", score: "21" }, { date: "13-Mar", score: "22" }, { date: "14-Mar", score: "23" }, { date: "15-Mar", score: "24" }, ], }, ], }, ];
let obj = { "string 1": { details: [ { id: 1, values: [ { date: "12-Mar", score: "15" }, { date: "13-Mar", score: "16" }, { date: "14-Mar", score: "17" }, { date: "15-Mar", score: "18" }, ], }, ], }, "string 2": { details: [ { id: 2, values: [ { date: "12-Mar", score: "16" }, { date: "13-Mar", score: "17" }, { date: "14-Mar", score: "18" }, { date: "15-Mar", score: "19" }, ], }, ], }, "string 3": { details: [ { id: "2", values: [ { date: "12-Mar", score: "21" }, { date: "13-Mar", score: "22" }, { date: "14-Mar", score: "23" }, { date: "15-Mar", score: "24" }, ], }, ], }, };
function getProperties(obj, key, unique = true, result = []) {
for(let k in obj) {
if (typeof(obj[k]) === 'object') {
getProperties(obj[k], key, unique, result);
} else if (k === key) {
result.push(obj[k]);
}
}
return unique ? [...new Set(result)]: result;
}
console.log('Dates (arr):', JSON.stringify(getProperties(arr, 'date', true)))
console.log('Scores (arr):', JSON.stringify(getProperties(arr, 'score', true)))
console.log('Dates (obj):', JSON.stringify(getProperties(obj, 'date', true)))
console.log('Scores (obj):', JSON.stringify(getProperties(obj, 'score', true)))
You can iterate over the top-level keys in your object like this:
for (let key in obj){
let val = obj[key]
/* From here you can proceed with finding all values
like you did with the array
*/
}

push element in a array of object javascript

I have an array of objects with objects and children and children can have elements
let array = {
account: "account 1",
children: [
{
account: "1",
},
{
account: "2",
},
],
total: {
debit: 96,
credit:96,
},
},
{
account: "account 2",
children: [
{
account: "1",
},
],
total: {
debit: 45,
credit: 96,
},
}
]
The expected array is to push an object to each of the children here and the object will be the total object we have at the bottom.
Expected Result:
let resultArray = {
account: "account 1",
children: [
{
account: "1",
},
{
account: "2",
},
{
debit: 96,
credit:96,
},
],
total: {
debit: 96,
credit:96,
},
},
{
account: "account 2",
children: [
{
account: "1",
},
{
debit: 45,
credit: 96,
},
],
total: {
debit: 45,
credit: 96,
},
},
Any suggestions for the same?
var resultArray = array.map((data) => {
const newChildrenArray = [...data.children];
newChildrenArray.push({...data.total});
return { ...data, children: newChildrenArray };
});
Note:
Your array and resultArray are not valid.
They should be like:
let array = [obj1, obj2]
Hope this will solve your problem!

Groupby an array and get elements as subarray using jquery

I have an array like below and need to transform this array with sub arrays
[{
author: " "
category: "test1"
date: "8 September 2020"
extension: null
id: 5
maintitle: "test"
siteName: "site1"
title: "test1"
url: ""
},
{
author: ""
category: "test1"
date: "10 September 2020"
extension: null
id: 4
maintitle: "test2"
siteName: "site1"
title: "test2"
url: ""
},
{
author: " "
category: "test3"
date: "2 September 2020"
extension: null
id: 1
maintitle: "test3"
siteName: "Site3"
title: "test3"
url: ""
}]
The output would look like this:
[{
id: 1,
date: "8 September 2020",
title: test1,
category: test1,
"files": {
"Site1": [{
author: " "
date: "8 September 2020",
extension: null,
title: "test1"
}, {
author: " ",
date: "10 September 2020"
extension: null,
title: "test2"
url: ""
}
]
}
},
[{
id: 2,
date: "8 September 2020",
title: "test3",
category: "test3",
"files": {
"site3": [{
author: " ",
date: "30 August 2020",
extension: null,
title: "test3",
url: ""
}]
}]
}]
Groupby need to do with sitename and Category using Jquery/javascript. Please help me on this. Any help is much appreciated.
You could take an array for the wanted groups and an iterative approach for the nested arrays.
const
data = [{ author: "Merin", category: "Forms", date: "8 September 2020", documentName: "Credit1 Forms", documentUrl: "", id: 5, siteName: "Credit", title: "Forms" }, { author: "Sandeep", category: "Forms", date: "10 September 2020", documentName: "AFAD1 Forms", documentUrl: "#", id: 4, siteName: "Credit", title: "Forms" }, { author: "Jithin", category: "Policies", date: "2 September 2020", documentName: "Credit1 Manuel", documentUrl: "#", id: 1, siteName: "Credit", title: "Policies" }],
groups = [['category', 'files'], ['siteName']],
result = data.reduce((r, o) => {
groups
.reduce((p, [key, children = o[key]], i) => {
let value, group;
({ [key]: value, ...o } = o);
group = p.find(g => g[key] === value);
if (!group) p.push(group = { ...(i === 0 ? { id: p.length + 1 } : {}), [key]: value, [children]: [] });
return group[children];
}, r)
.push(o);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sum column tabulator based on condition

I am trying to sum column value in tabulator with specific condition and follow this Custom Calculation Function
What I tried so far:
$(document).ready(function() {
function getSum(total, num) {
return total + num;
}
var adultCalc = function(values, data, calcParams) {
var tempvalue = [];
data.forEach(function(data) {
var count = data.age * data.qty;
tempvalue.push(count);
});
console.log('array', tempvalue);
console.log('total', tempvalue.reduce(getSum));
/*return tempvalue;*/
}
var tabledata = [{
id: 1,
name: "Oli Bob",
age: "12",
qty: "1",
dob: ""
},
{
id: 3,
name: "Christine Lobowski",
age: "42",
qty: "1",
dob: "22/05/1982"
},
{
id: 4,
name: "Brendon Philips",
age: "35",
qty: "2",
dob: "01/08/1980"
},
{
id: 5,
name: "Margret Marmajuke",
age: "16",
qty: "0",
dob: "31/01/1999"
},
{
id: 5,
name: "Marmajuke",
age: "17",
qty: "0",
dob: "31/01/1999"
},
{
id: 4,
name: "Philips",
age: "27",
qty: "0",
dob: "01/08/1980"
}
];
var table = new Tabulator("#example-table", {
height: 205,
data: tabledata,
layout: "fitColumns",
columns: [{
title: "Name",
field: "name",
width: 150
},
{
title: "Age",
field: "age",
bottomCalc: adultCalc
},
{
title: "Qty",
field: "qty"
},
{
title: "Date Of Birth",
field: "dob",
sorter: "date",
align: "center"
}
]
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://unpkg.com/tabulator-tables#4.1.4/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.1.4/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>
My formula is : age * qty push it into array and total it.
I'm success to get the value what i want and push it into array, but the problem is i can't sum the array with array reduce function.
I got this error
TypeError: reduce of empty array with no initial value
My problem just to get total sum of array.
Can someone tell me what's wrong with my code?
Thanks.
You need to provide initial value to reduce
console.log('total', tempvalue.reduce(getSum,0));
first time when you use reduce you have an empty array and which is causing reduce to produce an error. you can pass initial value and it should work as expected.
Note: If initialValue isn't provided, reduce() will execute the
callback function starting at index 1, skipping the first index. If
initialValue is provided, it will start at index 0.
$(document).ready(function() {
function getSum(total, num) {
return total + num;
}
var adultCalc = function(values, data, calcParams) {
var tempvalue = [];
data.forEach(function(data) {
var count = data.age * data.qty;
tempvalue.push(count);
});
console.log('array', tempvalue);
console.log('total', tempvalue.reduce(getSum,0));
/*return tempvalue;*/
}
var tabledata = [{
id: 1,
name: "Oli Bob",
age: "12",
qty: "1",
dob: ""
},
{
id: 3,
name: "Christine Lobowski",
age: "42",
qty: "1",
dob: "22/05/1982"
},
{
id: 4,
name: "Brendon Philips",
age: "35",
qty: "2",
dob: "01/08/1980"
},
{
id: 5,
name: "Margret Marmajuke",
age: "16",
qty: "0",
dob: "31/01/1999"
},
{
id: 5,
name: "Marmajuke",
age: "17",
qty: "0",
dob: "31/01/1999"
},
{
id: 4,
name: "Philips",
age: "27",
qty: "0",
dob: "01/08/1980"
}
];
var table = new Tabulator("#example-table", {
height: 205,
data: tabledata,
layout: "fitColumns",
columns: [{
title: "Name",
field: "name",
width: 150
},
{
title: "Age",
field: "age",
bottomCalc: adultCalc
},
{
title: "Qty",
field: "qty"
},
{
title: "Date Of Birth",
field: "dob",
sorter: "date",
align: "center"
}
]
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://unpkg.com/tabulator-tables#4.1.4/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.1.4/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>
It can be done even easier. And don't forget the second parameter (initial value) of Array.reduce method.
$(document).ready(function() {
function getSum(total, num) {
return total + num;
}
var adultCalc = function(values, data, calcParams) {
return data.map(function(d) {
return d.age * d.qty;
})
.reduce(getSum, 0);
}
//or even in ES6 style
const qtyCalc = (values, data, calcParams) =>
data.map(d => d.age * d.qty)
.reduce((t, n) => t + n * 2, 0);
var tabledata = [{
id: 1,
name: "Oli Bob",
age: "12",
qty: "1",
dob: ""
},
{
id: 3,
name: "Christine Lobowski",
age: "42",
qty: "1",
dob: "22/05/1982"
},
{
id: 4,
name: "Brendon Philips",
age: "35",
qty: "2",
dob: "01/08/1980"
},
{
id: 5,
name: "Margret Marmajuke",
age: "16",
qty: "0",
dob: "31/01/1999"
},
{
id: 5,
name: "Marmajuke",
age: "17",
qty: "0",
dob: "31/01/1999"
},
{
id: 4,
name: "Philips",
age: "27",
qty: "0",
dob: "01/08/1980"
}
];
var table = new Tabulator("#example-table", {
height: 205,
data: tabledata,
layout: "fitColumns",
columns: [{
title: "Name",
field: "name",
width: 150
},
{
title: "Age",
field: "age",
bottomCalc: adultCalc
},
{
title: "Qty",
field: "qty",
bottomCalc: qtyCalc
},
{
title: "Date Of Birth",
field: "dob",
sorter: "date",
align: "center"
}
]
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://unpkg.com/tabulator-tables#4.1.4/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.1.4/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>

Categories

Resources