I am looking to how you can pass arguments into a nested anonymous map function.
So in a function like the below, the values of red, green, blue in the nested map are hardcoded.
How can parameters be passed into the nested map?
function myFunction() {
const spreadsheetId = "###"; // Please set your Spreadsheet ID.
const grid = { sheetId: 0, startRow: 0, startCol: 0 }; // Please set your gridrange.
const values = [["sample value1", "sample value2"], ["sample value3", "sample value4"]]; // Please set your values as 2 dimensional array.
const request = [{
updateCells: {
range: {
sheetId: grid.sheetId,
startRowIndex: grid.startRow,
startColumnIndex: grid.startCol,
},
rows: values.map(r => ({
values: r.map(c => ({
** userEnteredFormat: { backgroundColor: { red: 1, green: 0.4, blue: 0.4 } }**,
userEnteredValue: { stringValue: c }
}))
})),
fields: "userEnteredFormat,userEnteredValue"
}
}];
Sheets.Spreadsheets.batchUpdate({ requests: request }, spreadsheetId);
}
Thank you in advance
In your situation, how about the following modification?
Modified script:
function myFunctionb() {
const spreadsheetId = "###"; // Please set your Spreadsheet ID.
const grid = { sheetId: 0, startRow: 0, startCol: 0 }; // Please set your gridrange.
const values = [["sample value1", "sample value2"], ["sample value3", "sample value4"]]; // Please set your values as 2 dimensional array.
const backgroundColors = [[[1, 0.4, 0.4], [0.4, 1, 0.4]], [[0.4, 0.4, 1], [0.4, 0.4, 0.4]]]; // Please set your background colors as 2 dimensional array.
const request = [{
updateCells: {
range: {
sheetId: grid.sheetId,
startRowIndex: grid.startRow,
startColumnIndex: grid.startCol,
},
rows: values.map((r, i) => ({
values: r.map((c, j) => ({
userEnteredFormat: { backgroundColor: { red: backgroundColors[i][j][0], green: backgroundColors[i][j][1], blue: backgroundColors[i][j][2] } },
userEnteredValue: { stringValue: c }
}))
})),
fields: "userEnteredFormat,userEnteredValue"
}
}];
Sheets.Spreadsheets.batchUpdate({ requests: request }, spreadsheetId);
}
When this script is run, 4 values are put from cell "A1" and also 4 different background colors are set from cell "A1".
Related
I have a JSON in which I save the GuildID and then again the UserID
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
Now I want to sort the users by XPIns from one Guild. I remember this code part here
let obj;
fs.readFile('./xpdata.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data)
var sorted = Object.entries(obj).sort((a, b) => b[1] - a[1])
});
In the end, the user with more should be in the 1st position (866935358448468008). Can anyone help me?
I've seen a similar question before but couldn't get it to work if there was a GuildID in front of it
The code I had done before (sorry for the sloppy code that was a year ago (Code is updated)):
let obj;
fs.readFile('./userdata.json', 'utf8', function (err, data) {
if (err) throw err;
try {
obj = JSON.parse(data)
} catch (error) {
if(error) return console.log("Ein Fehler ist aufgetreten! " + error);
}
var sorted = Object.entries(obj).sort((a, b) => b[1].Economy.Balance - a[1].Economy.Balance)
if(sorted.length > 10) sorted = sorted.slice(0, 10)
var lBString = "";
var s = 1;
sorted.forEach(user => {
let usertag = Data[user[0]].Tag
lBString += `${s}. ${usertag} • **${user[1].Economy.Balance}$**\n`
s = s += 1
})
let embed = {
title: `Leaderboard Balance`,
description: lBString,
color: 0xFFFF00,
thumbnail: {
url: client.user.avatarURL(),
},
timestamp: new Date(),
footer: {
text: footer,
icon_url: client.user.avatarURL(),
},
}
e.reply({embeds: [embed]});
});
If you simply want the highest ranking user in terms of "XPIns", I suggest you use a Array.reduce() call on the entries of the inner object.
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
const topUser = Object.entries(data['385524088980111362']).reduce((acc, cur) => (
acc[1]?.XPIns > cur[1]?.XPIns ? acc : cur
), []);
console.log(topUser);
What I do in cases like this is to use another object as index using a reference of the main array/object
ie:
var index = {};
// replace .id with the attribute you want to use. In your case XPins
index[ object.id ] = main_index_reference;
once you have generated the index, then you can get the keys using Object.keys( index ):
var keys = Object.keys( index );
keys.forEach( function( key ){
var element = main_object[ key ];
// do whatever with the element
} );
Your main_object remains unchanged. In your particular case you want the highest value, all you need to do is to extract the last element from the keys array.
You can try with this. However, the users do not have their ID inside their object, so you'd probably have to patch the ID before sorting.
const data = {
// if the guild could have list of users then it would have been much better
// instead of Object list with ID, Array of objects with ID in it works much faster..
"385524088980111362": {
"672748733737467936": {
// if we had user ID here, then it would have been better
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
function getSortedUsersByXPins(data, guildId) {
// if guild has array of users, then we won't need Object.values
const sorted = Object.values(data[guildId]).sort((user1, user2) => {
return user2.XPins - user1.XPins
});
return sorted;
}
const sorted = getSortedUsersByXPins(data, '385524088980111362');
console.log(sorted)
You can try it with this solution, in case you want to convert the object to a list. The main issue is the missing identifier if you work with a list.
This assumes that you would use a function like Object.entries before to convert it.
My recommendation: Include the id into the object and convert it to a list.
let guildList = [
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2,
"Id": "672748733737467936"
},
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7,
"Id": "866935358448468008"
}
];
let aSorted = guildList.sort((a, b) => b.XPIns-a.XPIns)
console.log(aSorted)
Just extract the player objects and sort them, pretty much the way you already described ((p1, p2) => p2.XPIns - p1.XPIns).
Here is an example:
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
}
const res = Object.fromEntries(Object.entries(data).map( ([gid, users]) => [gid, Object.entries(users).map(([id, u]) => ({id, ...u })).sort( (u1, u2) => u2.XPIns - u1.XPIns)] ))
console.log(res)
Note that you cannot create an object with player id as key without losing the order, since JS objects always put numeric keys in ascending order.
How to get values of views into single array and get the two largest values in that array. The below is not creating single array. Could someone please advise ?
const data = [
{
id: 1,
views: 5678,
textData: "Sun"
},
{
id: 2,
views: 2500,
textData: "Moon"
},
{
id: 3,
views: 3500,
textData: "Earth"
},
{
id: 4,
views: 1250,
textData: "Sky"
}
]
data.map(({id, views, textData}) =>{
let myArr = [];
myArr.push(views);
let result = Math.max(...myArr);
console.log(result);
})
Desired Array: [5678, 2500, 3500, 1250 ]
Final Output : [5678,3500 ]
You can use Array#map to create an array of the views properties, then sort it.
const data=[{id:1,views:5678,textData:"Sun"},{id:2,views:2500,textData:"Moon"},{id:3,views:3500,textData:"Earth"},{id:4,views:1250,textData:"Sky"}];
let res = data.map(x => x.views).sort((a,b) => b - a).slice(0, 2);
console.log(res);
Get result in one loop without sorting, but the code doesn't look very clean.
const data=[{id:1,views:5678,textData:"Sun"},{id:2,views:2500,textData:"Moon"},{id:3,views:3500,textData:"Earth"},{id:4,views:1250,textData:"Sky"}];
const values1 = []
const values2 = [0, 0]
data.forEach(d => {
values1.push(d.views)
values2[0] = Math.max(values2[0], Math.min(d.views, values2[1]))
values2[1] = Math.max(d.views, values2[1])
})
console.log('single values: ', values1)
console.log('two largest values: ', values2)
Tallying which color has a greater value in each array element for data. Then push the higher valued color into an empty object, and/or increment that color by 1. Lastly sort the totals object highest to lowest in terms of the totals property values and return highest valued color
Struggling with how to map over this structure array since property keys are not uniform. Should I destructure it?
*I can redesign data structure as needed, and if it's easier to solve with a different design, please let me know!
data = [
{ orange: 4, green: 4},
{ green: 0, yellow: 0},
{ yellow: 1, orange: 4 },
{ blue: 2, green: 1 },
{ blue: 2, yellow: 1 },
{ green: 3, yellow: 2 },
{ green: 1, blue: 3},
{ green: 5, yellow: 2 },
]
```
```
totals = {
blue: 3,
green: 2,
orange: 1,
}
```
solution:
```
highValueColor = blue
```
// PSEUDOCODE
//map over the array => data.map()
//identify highest value between two elements => propA - propB
//check to see if the color's (key) in the element has already been added to totals object
//IF the key does not yet exist, create a property in the tally object with the color(key) and set its value to 1
//IF the key is already listed in tally object, increment its property value by 1 => ++
//sort totals object => Math.max()
//return highest value color
`
Not sure how much help this is, #hopzebordah answer seems fine except that it looks like it counts a colour when both colours have the same value. (e.g. { orange: 4, green: 4} gets counted as orange).
I added a version with map in the comments as you seemed to be interested in that, but I might have misunderstood what you were trying to achieve.
If you don't need the sorted object and only the highest value, then you probably don't need to sort the object first. Hopefully highest_value_unsort demonstrates this.
const data = [
{ orange: 4, green: 4},
{ green: 0, yellow: 0},
{ yellow: 1, orange: 4 },
{ blue: 2, green: 1 },
{ blue: 2, yellow: 1 },
{ green: 3, yellow: 2 },
{ green: 1, blue: 3},
{ green: 5, yellow: 2 },
];
const pick_color = (color_obj) => {
const [[color1, val1], [color2, val2]] = Object.entries(color_obj);
return val1 === val2 ?
null :
val1 > val2 ?
color1 :
color2;
};
const unsorted = {};
for(const color_obj of data) {
const color = pick_color(color_obj);
if(color) {
unsorted[color] = (unsorted[color] ?? 0) + 1;
}
}
// version of the above using reduce:
// const unsorted = data.reduce((acc, val) => {
// const color = pick_color(val);
//
// return !color ?
// acc :
// { ...acc, [color]: (acc[color] ?? 0) + 1 };
// }, {});
// version of the above using map then reduce:
// const unsorted = data
// .map(pick_color)
// .reduce(
// (acc, color) => !color ?
// acc :
// { ...acc, [color]: (acc[color] ?? 0) + 1 },
// {}
// );
const sorted = Object.fromEntries(
Object.entries(unsorted)
.sort(([, a_val], [, b_val]) => b_val - a_val)
);
const highest_value = Object.entries(sorted)[0][0];
const highest_value_unsort = Object.entries(unsorted)
.reduce(
(acc, entry) => entry[1] > acc[1] ? entry : acc,
['none', 0]
)[0];
console.log(sorted);
console.log(highest_value);
console.log(highest_value_unsort);
Some reference links in case you're not familiar with some of the features used above:
reduce
Nullish coalescing operator (??)
Spread syntax
You're in luck as you are using JS!
It's super easy (or loosey-goosey, depending on your personal preference) to set/get data inside of JS objects using their keys using the { [someVariable]: value } notation. You can also check for existence of a key inside of an object using the in operator, like so:
const obj = { red: 'foo' };
const red = 'red';
console.log(red in obj) // true
console.log('red' in obj) // true
console.log(blue in obj) // false
So, combining that with a couple simple loops we can get this:
const data = [
{ orange: 4, green: 4},
{ green: 0, yellow: 0},
{ yellow: 1, orange: 4 },
{ blue: 2, green: 1 },
{ blue: 2, yellow: 1 },
{ green: 3, yellow: 2 },
{ green: 1, blue: 3},
{ green: 5, yellow: 2 },
];
const totals = {};
for (const colors of data) {
const [color1, color2] = Object.keys(colors);
let color = color1;
if (colors[color1] < colors[color2]) {
color = color2
}
totals[color] = totals[color] ? totals[color] + 1 : 1;
}
console.log(totals) // { orange: 2, green: 3, blue: 3 }
This isn't a performant solution by any means, but it is mainly held back by the structure of your data and needing to iterate over every value in order to check each key and its corresponding value.
Objects are very powerful in JS and form the basis of its flexibility. You may be able to leverage this to get a faster solution if you are eventually held back by performance issues depending on the size of the dataset.
Hi guys i got a complicated case for me
I have 4 array like this
[
{
"Id":1111111,
"OptionName":"Color",
"VariantName":"White"
},
{
"Id":2222222,
"optionName":"Size",
"VariantName":"XL"
},
{
"Id":3333333,
"OptionName":"Color",
"VariantName":"GREEN"
},
{
"Id":4444444,
"optionName":"Size",
"VariantName":"L"
}
]
So i want to merge the ID like
1 on 1, 1 on 2,2 on 1, 2 on 2
The result should be like this, but depend by variant name, so colours merge to size
[
{
"Id":1111111_2222222
...
},
{
"Id":1111111_4444444,
...
},
{
"Id":3333333_2222222,
...
},
{
"Id":3333333_4444444,
...
}
]
I already found how to group them by option Name, but how to merge it?
this is the code how i group them
const filteredVariantCats = variantCats
.map((a) => a.optionName)
.filter(onlyUnique)
.map((optionName) => {
let array = []
return variantCats
.filter((a) => a.optionName === optionName)
.map((a, idx) => {
array.push(a)
return a
})
})
UPDATE RESULT THAT I WANT TO RETURN IS THIS
{
id: null,
combinationStr: a.ID+"_"+b.ID,
name: a.variantName+' ,'+ b.variantName,
hex: '#000',
stock: 0,
price: 0,
priceDiscountType: OPTION.DISCOUNT_TYPE.NONE,
priceDiscount: 0,
weight: 10,
code: '',
attributeCode: 'a',
active: true,
productId: product.id from state,
}
Assume the syntax error and mis-matched cases are just error you make while writing the example and not actual mistakes in your actual code. If I understand correctly, you want to split the array into two groups, colors and sizes. Then generate all combinations between the two. Here is an example of how to do so. Since you mark ... in your expected output, I don't know what you actually expect so can only provide the Id field.
const arr = [
{
Id: 1111111,
OptionName: "Color",
VariantName: "White"
},
{
Id: 2222222,
OptionName: "Size",
VariantName: "XL",
},
{
Id: 3333333,
OptionName: "Color",
VariantName: "GREEN"
},
{
Id: 4444444,
OptionName: "Size",
VariantName: "L",
}
];
const colors = arr.filter(it => it.OptionName == "Color");
const sizes = arr.filter(it => it.OptionName == "Size");
let results = [];
for(let color of colors)
{
for(let size of sizes)
{
results.push({Id: `${color.Id}_${size.Id}`});
}
}
console.log(results);
Basically I have an array of objects. Each object has an array which I need to change the values.
I'm using React, so this is a state:
[
{
"points": [
60,
5,
60,
20,
70,
20,
70,
15
],
"finished": true,
"color": "#6292C6"
},
{
"points": [
80,
15,
80,
25,
90,
25
],
"finished": true,
"color": "#3FD971"
},
{
"cultureName": "",
"points": [],
"finished": false
}
]
What's the best way to change the points values of this state? I need to multiply them by a factor (4.96).
map your array, spread each object inside it overwriting only the property points (map multiplying each item by the factor 4.96)
const data = [{id: 1, points: [1,2,3]}, {id: 2, points: []}]
const changedData = data.map(item =>({
...item,
points : item.points.map(value => value * 4.96)
}))
console.log(changedData)
Use nested maps
const myData = [
{"points": [60,5,60,20,70,20,70,15],"finished": true,"color": "#6292C6"},
{"points": [80,15,80,25,90,25],"finished": true,"color": "#3FD971"},
{"cultureName": "","points": [],"finished": false}
]
const newArray = myData.map(elm=>{
const points = elm.points.map(point=> point*4.96)
return {...elm , points}
})
console.log(newArray)
const factor = 4.96
const arrayOfObject = [] // .. here your array of objects
const modifiedArrayOfObjects = arrayOfObject.map( stats => {
const newPoints = stats.points.map(point => point * factor)
stats.points = newPoints
return stats
}
Here I make a new array of objects, where I map each object to one, where each point has been multiplied by your factor.