Updating javascript string to an array - javascript

I got an URL containing a bunch of parameters, hereunder the following as well;
conditions=[{"name”:”foo”,”operator”:”bar”,”value":350000}]
This can also be the folowing
conditions=[]
and
conditions=[{"name”:”one”,”operator”:”two”,”value":350000}, {"name”:”three”,”operator”:”one”,”value”:22}]
It could theoretically also be
conditions=[{"name”:”one”,”operator”:”two”,”value":350000}, {"name”:”three”,”operator”:”one”,”value”:22}, {"name”:”four”,”operator”:”two”,”value”:22}, {"name”:”sixty”,”operator”:”three”,”value”:22}, ..]
Based on an input I want to change the conditions=[]. I got the following variables in my code
inputName, obj, valueOperator
These could contain the following values:
inputName = “three”
valueOperator = “two”
obj.value = 22
So from this i can construct the conditions as describer earlier. Now to my issue;
I want to break up the conditions=[] and check if there is anything in the brackets, if not, I’ll just add my new condition. If there is something, I want to check if the inputName matches any “name” in bracket. If not, I’ll just add my new condition. If it matches I want to update the value and operator with my new variables. When I’m done I want to put back together the conditions=[]. With the updated conditions. It will always only update one condition at a time.
I'm pretty much lost. Does anybody have a great idea?

From the explanation you have provided, i tried to replicate it. Hope this works.
const inputName = 'three';
const valueOperator = 'two';
const obj = 22;
let conditions = [
{ name: 'one', operator: 'two', value: 350000 },
{ name: 'two', operator: 'one', value: 22 }
];
if (conditions.length == 0) {
conditions.push({ name: inputName, operator: valueOperator, value: obj });
} else {
let found = false;
for (const condition of conditions) {
if (condition.name == inputName) {
condition.operator = valueOperator;
condition.value = obj;
found = true; // mark found as true when name found
}
}
// Insert values if not found in conditions
if (!found) {
conditions.push({ name: inputName, operator: valueOperator, value: obj });
}
}
console.log(conditions);

If you have the following url:
https://example.com/myfolder/?conditions=[{"name”:”foo”,”operator”:”bar”,”value":350000}]
then the value of the queryString parameter conditions is a JSON string.
To turn that value into a javascript object, you need the following:
// CAPTURE THE QUERY STRING IN A URLSearchParams OBJECT INSTANCE
let urlParams = new URLSearchParams(window.location.search);
// GET THE RELEVANT JSON STRING FROM urlParams
let conditionsJSON = urlParams.get('conditions');
// CONVERT THE JSON STRING INTO A JAVASCRIPT OBJECT
let conditionsObject = JSON.parse(conditionsJSON);
You will now have an array (conditionsObject) which looks like this:
[
{
name : "foo",
operator : "bar",
value : 350000
}
]
N.B. To avoid confusion, in javascript, an array is a specific kind of object - so the code above represents both an array and an object (because the former represents a subset of the latter).

This code should work
const inputName = 'foo'
const valueOperator = 'two'
const value = 22
const conditionString = 'condition=[{"name”:”foo”,”operator”:”bar”,”value":350000}]'
const data = JSON.parse(conditionString.substr(10).replace(/”/g, '"'))
const newData = { name: inputName, operator: valueOperator, value: value }
let ind = data.findIndex(v => v.name === inputName)
if (ind < 0) ind = data.length
data[ind] = newData
const newConditionsString = `conditions=${JSON.stringify(data)}`
console.log(newConditionsString)

First part of your problem can be taken care by the solution provided by Rounin. For the second part where you want to work on condition matching based on name, below code should be able to help you.
inputName="Three"
valueOperator = "two"
value = 22
if(conditionsObject.length!=0){
let index = conditionsObject.findIndex((item)=>item.name==inputName)
if(index!=-1){
conditionsObject[index].value = value
conditionsObject[index].operator = valueOperator
}
else{
conditionsObject.push({ name: inputName, operator: valueOperator, value: value })
}
else{
conditionsObject.push({ name: inputName, operator: valueOperator, value: value })
}
}

Related

Removing a keyword from a value inside an object - JS

I would like to remove the word ".com" from my object. Currently I can convert the object into a string however my filter is not working.
const items = [
{
company: 'datadog.com'
},
{
company: 'google.com'
},
{
company: 'amazon.com'
},
{
company: 'facebook.com'
}
];
var names = items.map(function(item) {
return item['company'];
});
names.toString();
var filter = names.replace(".com", "");
console.log(filter);
Simply use:
let names = items.map(item => item.company.replace(/[.]com$/, ''));
For each company domain name this returns the domain name with any final '.com' sequence removed.
Using the way you are doing it as a base, you can do something like this.
const items = [...youritems];
var names = items.map(function(item) {
return item['company'];
});
stringNames = JSON.stringify(names)
var filter = stringNames.replace(/.com/g, "");
filteredObject = JSON.parse(filter)
console.log(filteredObject)
But I don't think this is the safest way to go about it, or what you really want (it is not an array of objects). I would do something like this, using es6:
const items = [...youritems];
const newObject = items.map((item) => {
const companyNoCom = item["company"].replace(/.com/g, "")
newItem = {...item, company: companyNoCom}
return newItem
})
console.log(newObject)
This is safer to me, it keeps it an array of objects, and it is cleaner. It uses an arrow function and does not modify the underlying objects.

Best way to alter array of objects inside an object (using a string path)

This may be simpler than I think but is there an easy way to alter the array inside this object using a string:
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
This is what I am trying to achieve:
const name = "members[0].file_name" // STRING
temp = {...temp, [name]: 'changed'}
Output it's giving me:
Yes I can split that string to give me the keys and index then change the object the normal way but I was just wondering if there is an easier way about it.
You can take a look at lodash's set function that takes in a string path, and returns the nested object.
lodash does the parsing for you, so you don't have to
https://dustinpfister.github.io/2018/12/04/lodash_set/
You can use the eval() function which will return the object you want in accordance with a path
const temp = {
members: [{
file_name: 'abc',
file_link: 'www'
}]
}
const path = "members[0].file_name";
// Obtain last key (file_name)
const lastKey = path.split(".").at(-1);
// Obtain the path to the last key (members[0])
const previousPath = path.substr(0, path.length - (lastKey.length + 1));
// Get the object with the path (temp.members[0])
const e = eval(`temp.${previousPath}`)
// Modify object
e[lastKey] = "xyz";
console.log(temp)
You can achieve this the following way
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
const name = "file_name" // STRING
temp.members[0][name] = "changed";
console.log(temp);
Or like this:
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
const name = "file_name";
const arr = "members";
temp[arr][0][name] = "changed";
console.log(temp);

Get a key in a JavaScript object by its value and rename it

I have a list of variables that I will form into an array with keys and values. However, before making them as array I want to check if any of their values matches a
specific string and change their keys names into something else.
Lets say this is the list of variables
customer1 = "Jack", customerDate1 = "08/13/2021", customer2 = "Michael", customerDate2 = "01/01/2021", customer3 = "Luna",customerDate3 = "03/10/2021";
The array before running condition check will be
data = [{key1:"Jack", keyDate1:"08/13/2021",key2:"Michael", keyDate2:"01/01/2021",key3:"Luna", keyDate3:"10" }];
Lets say the condition is:
customerName = "Jack";
I want the cross check customerName variable with the following variables (customer1,customer2,customer3) and if the condition meets any of them, then their keys in the array changes:
for example the condition meets customer1 then both keys of customer1 and customerDate1 changes to something else, to become something like
data = [{conditionMet1:"Jack", conditionDateMet1:"08/13/2021",key2:"Michael", keyDate2:"01/01/2021",key3:"Luna", keyDate3:"10" }];
I am appreciating any help or guidance.
A little bit tricky as alghoritm but it works:
let data = [{key1:"Jhon", keyDate1:"08/13/2021",key2:"Eric", keyDate2:"01/01/2021",key3:"Jack", keyDate3:"10" }];
let i = 1;
let result = [];
let explored = [];
data.forEach(x => {
let resultObj = {};
for (const [key, val] of Object.entries(x)) {
let newKey = key;
let newKeyDate = null;
if (val === "Jack") {
newKey = "conditionMet" + i;
newKeyDate = "conditionDateMet" + i;
}
if (!explored.includes(key)) resultObj[newKey] = val;
if (newKeyDate) {
resultObj[newKeyDate] = x["keyDate" + i];
explored.push("keyDate" + i)
}
if(!key.includes("Date")) i++;
}
result.push(resultObj)
})
console.log(result)
Basically for each element in data I explore all the entries and if I found condition I add conditionMet1 and conditionDateMet1 to object, otherwise what I found on object itself.
Perhaps not very elegant, but for the example given you could do something like this:
if(specialCondition){
data = [{specialKey1:customer1, specialDate1:customerDate1,key2:customer2...];
}else{
data = [{key1:customer1, keyDate1:customerDate1,key2:customer2...];
}
I don't think it is possible to rename a key but you can always create a new key by
object["newKeyName"] = object.previousKey
And optionally you can remove the old key by
delete object.previousKey
That way you will remove the previous key if you don't want it anymore.
Say you have 6 variables.
customer1, customerDate1, customer2, customerDate2, customer3,customerDate3;
You could make an array, by customer
const data = [{
id: customer1,
date: customerDate1
},{
id: customer2,
date: customerDate2
},{
id: customer3,
date: customerDate3
}];
This is now quite useful. Say you want to know which customer meets some condition. (for example id is "Jack"), using Array.find
const jack = data.find(item => item.id === "Jack");
console.log(jack);
Or to find which customers have a date before "now", using Array.filter
const now = Date.now();
const beforeNow = data.filter(item => item.date < now);
console.log(beforeNow);

Check if element included in array of object in react js [duplicate]

I have an array like
vendors = [{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
} // and so on...
];
How do I check this array to see if "Magenic" exists? I don't want to loop, unless I have to. I'm working with potentially a couple thousand records.
No need to reinvent the wheel loop, at least not explicitly (using arrow functions, modern browsers only):
if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
/* vendors contains the element we're looking for */
}
or, better yet, use some as it allows the browser to stop as soon as one element is found that matches, so it's going to be faster:
if (vendors.some(e => e.Name === 'Magenic')) {
/* vendors contains the element we're looking for */
}
or the equivalent (in this case) find:
if (vendors.find(e => e.Name === 'Magenic')) {
/* same result as above, but a different function return type */
}
And you can even get the position of that element by using findIndex:
const i = vendors.findIndex(e => e.Name === 'Magenic');
if (i > -1) {
/* vendors contains the element we're looking for, at index "i" */
}
And if you need compatibility with lousy browsers then your best bet is:
if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
/* vendors contains the element we're looking for */
}
2018 edit: This answer is from 2011, before browsers had widely supported array filtering methods and arrow functions. Have a look at CAFxX's answer.
There is no "magic" way to check for something in an array without a loop. Even if you use some function, the function itself will use a loop. What you can do is break out of the loop as soon as you find what you're looking for to minimize computational time.
var found = false;
for(var i = 0; i < vendors.length; i++) {
if (vendors[i].Name == 'Magenic') {
found = true;
break;
}
}
No loop necessary. Three methods that come to mind:
Array.prototype.some()
This is the most exact answer for your question, i.e. "check if something exists", implying a bool result. This will be true if there are any 'Magenic' objects, false otherwise:
let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )
Array.prototype.filter()
This will return an array of all 'Magenic' objects, even if there is only one (will return a one-element array):
let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )
If you try to coerce this to a boolean, it will not work, as an empty array (no 'Magenic' objects) is still truthy. So just use magenicVendors.length in your conditional.
Array.prototype.find()
This will return the first 'Magenic' object (or undefined if there aren't any):
let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );
This coerces to a boolean okay (any object is truthy, undefined is falsy).
Note: I'm using vendor["Name"] instead of vendor.Name because of the weird casing of the property names.
Note 2: No reason to use loose equality (==) instead of strict equality (===) when checking the name.
The accepted answer still works but now we have an ECMAScript 6 native methods [Array.find][1] and [Array.some][2] to achieve the same effect.
Array.some
Use some If you only want to determine if an element exists i.e. you need a true/false determination.
Quoting MDN:
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
Array.find
Use find if you want to get the matched object from array else returns undefined.
Quoting MDN:
The find() method returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.
var arr = [
{
id: 21,
label: 'Banana',
},
{
id: 22,
label: 'Apple',
}
]
/* note : data is the actual object that matched search criteria
or undefined if nothing matched */
var data = arr.find(function(ele) {
return ele.id === 21;
});
if (data) {
console.log('found');
console.log(data); // This is entire object i.e. `item` not boolean
}
/* note : doesExist is a boolean thats true or false depending on of whether the data was found or not */
var doesExist = arr.some(function(ele) {
return ele.id === 21;
});
See my jsfiddle link There is a polyfill for IE provided by mozilla
Here's the way I'd do it
const found = vendors.some(item => item.Name === 'Magenic');
array.some() method checks if there is at least one value in an array that matches criteria and returns a boolean.
From here on you can go with:
if (found) {
// do something
} else {
// do something else
}
Unless you want to restructure it like this:
vendors = {
Magenic: {
Name: 'Magenic',
ID: 'ABC'
},
Microsoft: {
Name: 'Microsoft',
ID: 'DEF'
} and so on...
};
to which you can do if(vendors.Magnetic)
You will have to loop
May be too late, but javascript array has two methods some and every method that returns a boolean and can help you achieve this.
I think some would be most appropriate for what you intend to achieve.
vendors.some( vendor => vendor['Name'] !== 'Magenic' )
Some validates that any of the objects in the array satisfies the given condition.
vendors.every( vendor => vendor['Name'] !== 'Magenic' )
Every validates that all the objects in the array satisfies the given condition.
As per ECMAScript 6 specification, you can use findIndex.
const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');
magenicIndex will hold either 0 (which is the index in the array) or -1 if it wasn't found.
As the OP has asked the question if the key exists or not.
A more elegant solution that will return boolean using ES6 reduce function can be
const magenicVendorExists = vendors.reduce((accumulator, vendor) => (accumulator||vendor.Name === "Magenic"), false);
Note: The initial parameter of reduce is a false and if the array has the key it will return true.
Hope it helps for better and cleaner code implementation
You cannot without looking into the object really.
You probably should change your structure a little, like
vendors = {
Magenic: 'ABC',
Microsoft: 'DEF'
};
Then you can just use it like a lookup-hash.
vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined
const check = vendors.find((item)=>item.Name==='Magenic')
console.log(check)
Try this code.
If the item or element is present then the output will show you that element. If it is not present then the output will be 'undefined'.
Testing for array elements:
JS Offers array functions which allow you to achieve this relatively easily. They are the following:
Array.prototype.filter: Takes a callback function which is a test, the array is then iterated over with is callback and filtered according to this callback. A new filtered array is returned.
Array.prototype.some: Takes a callback function which is a test, the array is then iterated over with is callback and if any element passes the test, the boolean true is returned. Otherwise false is returned
The specifics are best explained via an example:
Example:
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
} //and so on goes array...
];
// filter returns a new array, we instantly check if the length
// is longer than zero of this newly created array
if (vendors.filter(company => company.Name === 'Magenic').length ) {
console.log('I contain Magenic');
}
// some would be a better option then filter since it directly returns a boolean
if (vendors.some(company => company.Name === 'Magenic')) {
console.log('I also contain Magenic');
}
Browser support:
These 2 function are ES6 function, not all browsers might support them. To overcome this you can use a polyfill. Here is the polyfill for Array.prototype.some (from MDN):
if (!Array.prototype.some) {
Array.prototype.some = function(fun, thisArg) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.some called on null or undefined');
}
if (typeof fun !== 'function') {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
for (var i = 0; i < len; i++) {
if (i in t && fun.call(thisArg, t[i], i, t)) {
return true;
}
}
return false;
};
}
Simplest method so far:
if (vendors.findIndex(item => item.Name == "Magenic") == -1) {
//not found item
} else {
//found item
}
My approach to solving this problem is to use ES6 and creating a function that does the check for us. The benefit of this function is that it can be reusable through out your project to check any array of objects given the key and the value to check.
ENOUGH TALK, LET'S SEE THE CODE
Array
const ceos = [
{
name: "Jeff Bezos",
company: "Amazon"
},
{
name: "Mark Zuckerberg",
company: "Facebook"
},
{
name: "Tim Cook",
company: "Apple"
}
];
Function
const arrayIncludesInObj = (arr, key, valueToCheck) => {
return arr.some(value => value[key] === valueToCheck);
}
Call/Usage
const found = arrayIncludesInObj(ceos, "name", "Tim Cook"); // true
const found = arrayIncludesInObj(ceos, "name", "Tim Bezos"); // false
2021 Solution*
Lodash .some (docs) is a clean solution, if you use the _matchesProperty (docs) shorthand:
_.some(VENDORS, ['Name', 'Magenic'])
Explanation
This will iterate through the VENDORS Array looking for an element Object with the Name key having a value of the String 'Magenic'. Once it finds this element, it returns true and stops iterating. If it doesn't find the element after looking through the entire Array, it returns false.
Code snippet
const VENDORS = [{ Name: 'Magenic', ID: 'ABC' }, { Name: 'Microsoft', ID: 'DEF' }];
console.log(_.some(VENDORS, ['Name', 'Magenic'])); // true
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
* Note that this uses the popular lodash library to achieve the simplest/shortest possible solution. I'm offering this as an alternative to the existing vanilla JS solutions, for those who are interested.
You have to loop, there is no way around it.
function seekVendor(vendors, name) {
for (var i=0, l=vendors.length; i<l; i++) {
if (typeof vendors[i] == "object" && vendors[i].Name === name) {
return vendors[i];
}
}
}
Of course you could use a library like linq.js to make this more pleasing:
Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();
(see jsFiddle for a demo)
I doubt that linq.js will be faster than a straight-forward loop, but it certainly is more flexible when things get a little more complicated.
Correct me if i'm wrong..
i could have used forEach method like this,
var found=false;
vendors.forEach(function(item){
if(item.name === "name"){
found=true;
}
});
Nowadays i'm used to it ,because of it simplicity and self explanatory word.
Thank you.
Functions map, filter, find, and similar are slower than the simple loop.
For me they also less readable than the simple loop and harder to debug. Using them looks like a kind of irrational ritual.
Better have something like this:
arrayHelper = {
arrayContainsObject: function (array, object, key){
for (let i = 0; i < array.length; i++){
if (object[key] === array[i][key]){
return true;
}
}
return false;
}
};
And use it like this with given OP example:
vendors = [{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
let abcObject = {ID: 'ABC', Name: 'Magenic'};
let isContainObject = arrayHelper.arrayContainsObject(vendors, abcObject, 'ID');
if you're using jquery you can take advantage of grep to create array with all matching objects:
var results = $.grep(vendors, function (e) {
return e.Name == "Magenic";
});
and then use the results array:
for (var i=0, l=results.length; i<l; i++) {
console.log(results[i].ID);
}
You can use lodash. If lodash library is too heavy for your application consider chunking out unnecessary function not used.
let newArray = filter(_this.props.ArrayOne, function(item) {
return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
});
This is just one way to do this. Another one can be:
var newArray= [];
_.filter(ArrayOne, function(item) {
return AllSpecies.forEach(function(cItem){
if (cItem.speciesId == item.speciesId){
newArray.push(item);
}
})
});
console.log(arr);
The above example can also be rewritten without using any libraries like:
var newArray= [];
ArrayOne.filter(function(item) {
return ArrayTwo.forEach(function(cItem){
if (cItem.speciesId == item.speciesId){
newArray.push(item);
}
})
});
console.log(arr);
Hope my answer helps.
Many answers here are good and pretty easy. But if your array of object is having a fixed set of value then you can use below trick:
Map all the name in a object.
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
var dirtyObj = {}
for(var count=0;count<vendors.length;count++){
dirtyObj[vendors[count].Name] = true //or assign which gives you true.
}
Now this dirtyObj you can use again and again without any loop.
if(dirtyObj[vendor.Name]){
console.log("Hey! I am available.");
}
To compare one object to another, I combine a for in loop (used to loop through objects) and some().
You do not have to worry about an array going out of bounds etc, so that saves some code. Documentation on .some can be found here
var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];
var objectsFound = [];
for(let objectNumber in productList){
var currentId = productList[objectNumber].id;
if (theDatabaseList.some(obj => obj.id === currentId)) {
// Do what you need to do with the matching value here
objectsFound.push(currentId);
}
}
console.log(objectsFound);
An alternative way I compare one object to another is to use a nested for loop with Object.keys().length to get the amount of objects in the array. Code below:
var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];
var objectsFound = [];
for(var i = 0; i < Object.keys(productList).length; i++){
for(var j = 0; j < Object.keys(theDatabaseList).length; j++){
if(productList[i].id === theDatabaseList[j].id){
objectsFound.push(productList[i].id);
}
}
}
console.log(objectsFound);
To answer your exact question, if are just searching for a value in an object, you can use a single for in loop.
var vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
for(var ojectNumbers in vendors){
if(vendors[ojectNumbers].Name === 'Magenic'){
console.log('object contains Magenic');
}
}
Alternatively you can do:
const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));
var without2 = (arr, args) => arr.filter(v => v.id !== args.id);
Example:
without2([{id:1},{id:1},{id:2}],{id:2})
Result:
without2([{id:1},{id:1},{id:2}],{id:2})
You can try this its work for me.
const _ = require('lodash');
var arr = [
{
name: 'Jack',
id: 1
},
{
name: 'Gabriel',
id: 2
},
{
name: 'John',
id: 3
}
]
function findValue(arr,value) {
return _.filter(arr, function (object) {
return object['name'].toLowerCase().indexOf(value.toLowerCase()) >= 0;
});
}
console.log(findValue(arr,'jack'))
//[ { name: 'Jack', id: 1 } ]
const a = [{one:2},{two:2},{two:4}]
const b = a.filter(val => "two" in val).length;
if (b) {
...
}
I would rather go with regex.
If your code is as follows,
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
I would recommend
/"Name":"Magenic"/.test(JSON.stringify(vendors))

get the highest role from array

I currently have an array u._roles that is filled with id's from groups like "581199939464462340".
Secondly I have a dictionary where the key is a role id and the value is the name, like {key: "581199939464462340", value: "Member"}.
Now I want to get the name of the "highest" role of the array. Currently I have this ugly if statement but I think that can be done better, but how? (The array u._roles is read only).
u._roles could look like this:
["5812040340469414946", "581200340469415946", "581209222700597248"] so the "highest" would be "581200340469415946" (second if). (And then get the name of this id from the dictionary roleMap)
var Rank;
if (u._roles.includes("581199939464462340")) {
Rank = roleMap["581199939464462340"]; // highest
} else if (u._roles.includes("581200340469415946")) {
Rank = roleMap["581200340469415946"]; //
} else if (u._roles.includes("581214123334041620")) {
Rank = roleMap["581214123334041620"]; //
} else if (u._roles.includes("588976480017448988")) {
Rank = roleMap["588976480017448988"]; //
} else if (u._roles.includes("581203853635223574")) {
Rank = roleMap["581203853635223574"]; //
} else if (u._roles.includes("581209222700597248")) {
Rank = roleMap["581209222700597248"]; //
} else if (u._roles.includes("592436270031175681")) {
Rank = roleMap["592436270031175681"]; // lowest
} else {
Rank = "";
}
Highest don't mean the highest number. Its just an order I like to use.
I completely changed this answer with some new insight. Hopefully this is a bit more helpful.
const rolePriority = {a:1, b:2, c:3, d:4};
const u = {"_roles": ['b','c', 'a']};
const rankNumber = u._roles.reduce((highest, role) => {
const rank = rolePriority[role];
return rank < highest ? rank : highest;
}, Infinity);
const rank = rankNumber === Infinity ? "" : roleMap[rankNumber]
We just save the right order in an array, loop it and check whether the value is included in roles. If yes find will return it and we can put it into roleMap[findvalue].
let order = ["581199939464462340", "581200340469415946", "581214123334041620", "588976480017448988", "581203853635223574", "581209222700597248","592436270031175681"],
roles = ["5812040340469414946", "581200340469415946", "581209222700597248"];
let rank = order.find(v => roles.includes(v));
console.log(rank) // => 581200340469415946
Replace the rank line in your code with:
let rank = roleMap[order.find(v => roles.includes(v))]
If your order or amount of elements in orders is likely to change this will be messy, if not, you can just save them for comparison like this.
Firstly copy the array, then sort it by the role property and take the first element.
var data = [{
name: "Rank 1",
role: "5812040340469414946",
},
{
name: "Rank 2",
role: "581200340469415946"
},
{
name: "Rank 3",
role: "581209222700597248"
}
];
// Copy the source array to avoid mutating it using destructuring it
var copy = [...data];
// Sort by role property
var rank = copy.sort((a, b) => (+a.role) - (+b.role))[0].name;
console.log(rank);

Categories

Resources