Discord.js: Pushing to array is combining strings - javascript

I am editing an embed message to update users that have "signed up" to a list by reacting. However, after my array length gets to 2, it begins combining the strings of the entire array before adding the new entry. Here is my code:
let newParticipant = getNickname(guildMembers) || user.tag;
//this line exists because "value" cannot be empty in an embed field
//so this removes the placeholder on the first entry
if (newEmbed.fields[2].value[0] === "0") {
newEmbed.fields[2].value = [
`${newEmbed.fields[2].value.length}. ${newParticipant}`,
];
} else {
let participants = [newEmbed.fields[2].value];
let newEntry = participants.length + 1 + ". " + newParticipant;
participants.push(newEntry);
newEmbed.fields[2] = { name: "Participants", value: participants };
console.log(newEmbed.fields[2].value);
}
However this is the output I'm getting after 3 reactions:
[ '1. Cardinal' ]
[ '1. Cardinal', '2. Cardinal' ]
[ '1. Cardinal\n2. Cardinal', '2. Cardinal' ]
Is this something native to discord? Is my logic bad? I've tried using a spread operator when bringing in the array and several other things...

this worked. thank you Worthy Alpaca. I still wish I knew what exactly was happening lol.
let participants = newEmbed.fields[2].value;
let num = participants.split("\n").length;
let newEntry = `\n${num + 1}. ${newParticipant}`;
participants += newEntry;
newEmbed.fields[2] = { name: "Participants", value: participants };
console.log(newEmbed.fields[2].value);

Related

How to combine JS Objects with duplicate key/values

sorry if this is a easy question, I am just having a hard time trying to figure out how I would tackle this problem.
For example, I have 2 Objects as below:
cont oldCar = {
model: 'Honda',
notes: {
id: 1,
timestamp: 2000,
text: 'is old'
}
}
cont oldCar = {
model: 'Toyota',
notes: {
id: 1,
timestamp: 4000,
text: 'is new'
}
}
I want to try and combine the above two objects. I know they have same key's so I wanted to merge the values of each key if they are the same. Such as:
mode: 'Honda / Toyota'
I tried the following:
let merged = {...obj1, ...obj2};
But this will merge both objects but it only retains the values from the right object. I was trying to do a for loop and add check if the key is same in both objects then combine the values together but I keep getting lost and it is hard to visualise. If someone could help me understand how i can create an for loop to start the comparison that would help me in completing the rest.
To do this merge, perhaps you could do some array-reduce, it will also work with a list of unspecific size:
let array = Array(oldCar1,oldCar2)
let result = array.reduce((a,b)=> {
let r = Object.assign({},a)
r.notes = Object.assign({},r.notes)
if (a.model != b.model) {
r["model"] = a.model + " / " + b.model;
}
if (a.notes.text != b.notes.text) {
r.notes.text = a.notes.text + " / " + b.notes.text;
}
// ...
return r;
})
What exactly do you want to achieve? Is it only the merging of model prop or something else?
Do you have more than two objects, is the amount of objects dynamic? If there are only two objects you can do that without any loops.
const merged = {
model: `${firstCar.model} / ${secondCar.model}`,
// etc...
};
But as I said before - if the amount of objects is not constant then you'd need a map that would:
go through each car
try and find a match by ID from other cars
if there's a match return a merged result, if there's no match return the object as it is
Let me know what exactly are your needs here.

JavaScript user prompt 2d array lookup - Elf Name Generator

Started with what I thought was a simple idea for a class activity for our JavaScript unit, but falling foul best way to read a JavaScript 2D array based on a user input.
How can I get it to look up the users entry in the first index of the array and output the value in the second index? I need to tell it at some point which index to read and which to output, via similar syntax to [0][1] I imagine, but trial and error is getting me far.
Perhaps there is a better way??
Here is what I have so far, which just outputs the first array entry in its entirety - "A","Angelic"
var firstNames = [
["A","Angelic"],
["B","Blustery"],
........
["Y","Cheery"],
["Z","Dancy"]
];
var firstInitial = window.prompt("What is the first letter of your first name: ").toUpperCase();
let elfFirstName = firstNames.find(firstSearch);
function firstSearch(firstInitial) {
return firstInitial;
}
window.alert("Your Elf Name is " + elfFirstName);
</script>```
Thanks
You could take an object with the initials as keys.
const
firstNames = {
A: "Angelic",
B: "Blustery",
Y: "Cheery",
Z: "Dancy"
},
firstInitial = window.prompt("What is the first letter of your first name: ")[0].toUpperCase(),
elfFirstName = firstNames[firstInitial];
console.log("Your Elf Name is " + elfFirstName);
You do not use find right. It needs to look at the first index of your array that is passed in.
function firstSearch(item) {
return item[0] === firstInitial;
}
So
var firstNames = [
["A", "Angelic"],
["B", "Blustery"],
["Y", "Cheery"],
["Z", "Dancy"]
];
var firstInitial = window.prompt("What is the first letter of your first name: ").toUpperCase();
const elfFirstName = firstNames.find(firstSearch)[1];
function firstSearch(item) {
return item[0] === firstInitial;
}
window.alert("Your Elf Name is " + elfFirstName);
Better solution as I pointed out in the comments is using an array
var firstNames = {
A: "Angelic",
B: "Blustery",
Y: "Cheery",
Z: "Dancy"
};
var firstInitial = window.prompt("What is the first letter of your first name: ").toUpperCase();
const elfFirstName = firstNames[firstInitial];
window.alert("Your Elf Name is " + elfFirstName);

If name & operator matches, update the recent value, not working in the second iteration

I have an array of filters, where i get the name of filter, operator & value
e.g.
[{name="pricing.price", op="gte", value=10000}, {name="pricing.price", op="gte", value=10000}]
when the user refreshes after applying the filter, the last filters are saved into this.savedFilters
and after the refresh, the user can add new filters or modify the existing filters.
add new filters -> works fine
modify existing filters -> NOT working fine
I made a function, which is partially doing the job, if I am running it, it's updating the value only once, and then next time I update, it's not updating anything.
JSFiddle: https://jsfiddle.net/cdr8btwe/
//if there are no saved filters, the new filters are the final filters
if (!this.savedFilters) {
this.finalFilters = this.freshFilters;
} else {
//concat the new & saved filters & move into a temp array
this.tempArrayOfFilters =
this.freshFilters.concat(this.savedFilters);
//forEach loop to check
this.tempArrayOfFilters.forEach((value) => {
const key = value['name'] + '_ ' + value['op'];
if (this.mapping[key]) {
} else {
this.finalFilters.push(value);
this.mapping[key] = true;
}
});
}
console.log('finalFilters:', this.finalFilters);
[
{name:"pricing.price",op:"gte",value:1234}, {name:"pricing.price",op:"lte",value:1111}
]
When the person is modifying saved filters,
lets say
this.freshfilters = [{"name":"pricing.price","op":"gte","value":5678},
{"name":"pricing.price","op":"gte","value":9999}]
output is coming
[{name:"pricing.price", op:"gte", value:1234},
{name:"pricing.price", op:"lte", value:1111}]
the output should be
[{name:"pricing.price",op:"gte",value:5678},{name:"pricing.price",op:"lte",value:9999}]
because if name & op is the same, just update the value.
Try this, I'm not sure exactly what you are trying to do but hopefully this will be of some use to you.
let arr1 = [{name: "pricing.price", op:"gte", value:1234}];
let arr2 = [{name: "pricing.price", op:"gte", value:5678}];
let arr3 = [{name: "pricing.price", op:"lte", value:1111}];
let arr5 = [{name: "pricing.price", op:"lte", value:9999}];
let arr4 = []
arr4 = arr4.concat(arr1, arr2, arr3, arr5);
final_arr = []
mapping = {} // truthy mapping of name and p.p
arr4.forEach((value) => {
key = value["name"]+'_ '+value["op"]
final_arr[key] = value;
//if (mapping[ key ]) {
//} else {
//final_arr.push(value)
mapping[key] = true
//}
})
//Current Output
/*
[
{name:"pricing.price", op:"gte", value:1234},
{name:"pricing.price", op:"lte", value:1111}
]
*/
//Expected Output
/*
[
{"name":"pricing.price","op":"gte","value":5678},
{"name":"pricing.price","op":"lte","value":9999}
]
*/
console.log('final_arr: ', final_arr)
jsfiddle

Remove singular element from an object's key array

I have an object that has multiple keys and each of these keys has an array storing multiple elements. I want to be able to remove a specified element from the key's array.
I have tried using the delete keyword as well as the filter method, but I have been unsuccessful. I'm a total newbie to JS so I appreciate any assistance. Also, I want to do this using ONLY JavaScript, no libraries.
Here is the code where I am creating my object:
function add(task, weekdayDue) {
let capitalWeekday = weekdayDue.charAt(0).toUpperCase() +
weekdayDue.slice(1);
if (toDoList[capitalWeekday] === undefined) {
let subArr = [];
toDoList[capitalWeekday] = subArr.concat(task);
} else {
toDoList[capitalWeekday].push(task);
}
}
and here is the code as I have it now. Clearly it is not producing the correct result:
function remove(task, weekdayDue) {
let capitalWeekday = weekdayDue.charAt(0).toUpperCase() +
weekdayDue.slice(1);
delete toDoList.capitalWeekday[task]
//the below code is working; i want to send this to another
array
if (archivedList[capitalWeekday] === undefined) {
let subArr = [];
archivedList[capitalWeekday] = subArr.concat(task);
} else {
archivedList[capitalWeekday].push(task);
}
};
add('laundry', 'monday');
add('wash car', 'monday');
add ('vacuum', 'tuesday');
add('run errands', 'wednesday');
add('grocery shopping', 'wednesday');
// the output is: { Monday: [ 'laundry', 'wash car' ],
Tuesday: [ 'vacuum' ],
Wednesday: [ 'run errands', 'grocery shopping' ] }
Then let's say I want to remove 'wash car' from Monday I was trying:
remove('wash car', 'monday');
console.log(toDoList)
// The output is an empty object {}
I personally would refactor a bit your code, but I've worked a bit around it to fix some issues.
First of all, you shouldn't use delete for your scenario, because it will reset the item at the nth position of the array with the default value, which is undefined.
Usually, for that kind of operations, since you deal with strings, you rather take a look at the first occurrence of your item in the array, take its index, and use splice (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) to actually remove the item from the array.
In this way, you end up with a clean array without invalid items in it.
Below is the working code (with the mentioned fixes) that does what you asked. As a side note, I would suggest you to avoid working with strings for such purposes, but I would rather tackle objects with unique ids, so that it's significantly easier to keep track of them between arrays and objects.
Additionally, there are some cases that you didn't think about, for instance I can think about calling remove by giving an invalid task, so you may work a bit around the code below to handle the case where taskIndex is -1 (meaning that no item was found with that index).
var toDoList = {}, archivedList = {};
function add(task, weekdayDue) {
let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + weekdayDue.slice(1);
if (toDoList[capitalWeekday] === undefined) {
let subArr = [];
toDoList[capitalWeekday] = subArr.concat(task);
} else {
toDoList[capitalWeekday].push(task);
}
}
function remove(task, weekdayDue) {
let capitalWeekday = weekdayDue.charAt(0).toUpperCase() + weekdayDue.slice(1);
let taskIndex = toDoList[capitalWeekday].indexOf(task);
toDoList[capitalWeekday].splice(taskIndex, 1);
//delete toDoList[capitalWeekday][taskIndex];
if (archivedList[capitalWeekday] === undefined) {
let subArr = [];
archivedList[capitalWeekday] = subArr.concat(task);
} else {
archivedList[capitalWeekday].push(task);
}
};
add('test', 'monday');
add('wash car', 'monday');
remove('wash car', 'monday');
console.log(toDoList);
console.log(archivedList);
You are on the right path. Maybe the trouble you had with filter is because filter will return a new Array and not modify the current one. You could update your remove function and replace the line:
delete toDoList.capitalWeekday[task]
with
toDoList.capitalWeekday = toDoList.capitalWeekday.filter((item) => {return item !== task});
function remove(task, weekdayDue) {
let capitalWeekday = weekdayDue.charAt(0).toUpperCase() +
weekdayDue.slice(1);
// Assign new array with all elements but task
toDoList[capitalWeekday] = toDoList[capitalWeekday].filter(i => i !== task)
};
add('foo'...
add('bar'...
"{
"Baz": [
"Foo",
"Bar"
]
}"
remove('foo'...
"{
"Baz": [
"Bar"
]
}"

Get values from nested array that are dynamically generated

I am working on a chrome plugin that fetches data. But now i have been running into a problem, I have been asked to put together a nested array with all the data I have retrieved but I have no clue on how to pull this off.
What i want to create:
var messagedata [{
time: messageTime,
Date: messageDate,
Text: messageText
{
time: messageTime,
Date: messageDate,
Text: messageText
}
}];
Note that I know how to create the above when I have the variables. That is not the problem. But in this case i do not know how to declare the variables for each message from the array that is generated.
What i need is a nested array for each message that is in the HTML. So the above example displays 2 arrays but it could be 54 for example.
Code i use to generate normal array:
adiv.innerHTML = cleanupDocString;
trs = adiv.querySelectorAll('tr[bgcolor="#FFFFFF"]');
trs.forEach(function(tr) {
var d = [];
tr.querySelectorAll("td")
.forEach(function(td) {
var img = td.querySelector("img"),
src = img && img.attributes.getNamedItem("src").value;
d.push(src || td.textContent);
});
msgs.push(d);
});
The code above puts this out in console (this example has 2 messages inside it, there are also arrays with 54 messages):
0:Array(6)
0:"2017-08-31T00:00:00"
1:"13:22"
2:"MessageType"
3:ā€¯ClientName"
4:"Subject "
5:"messageText"
length:6
proto:Array(0)
1:Array(6)
0:"2017-08-31T00:00:00"
1:"13:21"
2:" MessageType "
3: "ClientName"
4:" Subject "
5:" messageText "
lenth:6
proto:Array(0)
To make the question easier:
I need to know how i can put the data into a variable that i fetch from the array above. I just don't know how to do it so its dynamic.
What i tried:
var messageDate = msgs[0][0];
var messageTime = msgs[0][1];
var messageType = msgs[0][2];
var messageClient = msgs[0][3];
var messageSubject = msgs[0][4];
var messageText = msgs[0][5];
The above code works but only fetches the first message. I need all the messages that are on the page that is provided. I tried using a ID in the first [] but that also didn't give me the desired result.
Thanks for your help and patience in advance.
Output and code has been slightly edited so it hides personal information
i am assuming msgs is arrray of arrays and the order of properties is guaranteed
var mappedArray = msgs.map((msg)=> {
return {
messageDate : msg[0];
messageTime : msg[1];
messageType : msg[2];
messageClient : msg[3];
messageSubject : msg[4];
messageText :msg[5];
}
})
Edit1
you can use arrayconcat
var mergedArray = mappedArray.concat(otherArray);
To transform the multidimensional array to an array of objects with the help of Array.prototype.map and a simple helper dictionary which defines the index => property mapping.
var messages = [
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
],
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
],
[
"2017-08-31T00:00:00",
"13:22",
"MessageType",
"ClientName",
"Subject",
"messageText",
"unwanted value"
]
];
var mappingDef = {
0: 'messageDate',
1: 'messageTime',
2: 'messageType',
3: 'messageClient',
4: 'messageSubject',
5: 'messageText'
};
function transformMessages(messages, mappingDef) {
return messages.map(function(message) {
var obj = {};
for(var index in mappingDef) {
if(mappingDef.hasOwnProperty(index)) {
obj[mappingDef[index]] = message[index];
}
}
return obj;
});
}
console.log(transformMessages(messages, mappingDef));

Categories