I've got to create a list of contacts using javascript which allows the user to enter contacts, and so that the program runs until the user quits. I'm a little lost as to whether I need to add alerts or not. Here's some of my code below, it's a work in progress so there are no expected console outcomes from it as yet.
/*
Activity: Contact manager
*/
// TODO: Complete the program
var Contact = {
// initialise contacts
init: function(last_name, first_name) {
this.last_name = last_name;
this.first_name = first_name;
},
describe: function () {
var description = this.last_name + "," + this.first_name;
return description
},
// add a contact
contact_list: function () {
var list_of_contacts = []
}
}
var contact1 = Object.create(Contact);
contact1.init("Smith", "John");
var contact2 = Object.create(Contact);
contact2.init("Doe", "Jane");
var contact_list = [];
contact_list.push(contact1);
contact_list.push(contact2);
This is what the console should look like, if the exercise is completed successfully:
Welcome to your contacts manager!
1: List contacts
2: Add a contact
0: Quit
Upon providing the option 1:
Here's the list of all your contacts:
Last name: Smith, first name: John
The rest is almost identical.
You already have a list, you are pusing them to the array: contact_list.push(contact1);
In order to log output a list, all you have to do is loop the array and print each name;
let output = "contacts: ";
for(let i=0;i< contact_list.length; i++){
output+= "Last name:" + contact_list[i].last_name + ", first name:" +contact_list[i].first_name ;
}
console.log(output);
Related
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);
I'm trying to create an object that is updated dynamically.
Here's the setup of the type of object I'd like to create (note: I may add other things, such as address, country, etc to the keys):
var contacts = {"Bruce Wayne":{"phone number":'123-456-7890', "email":"bwayne#night.com"}, "Alfred":{"phone number" :'987-654-3210', "email": "alfred#yourang.com"}, "Clark Kent":{"phone number":'951-753-8520', "email":"nothing#krypton.com"}}
So for each name (Bruce Wayne, Alfred, ...) I have some keys assigned to them.
I'm using npm faker to generate some fake data to try and populate an array like the above, with the outline
I'm able to get a loop going, but it always returns the last iteration's data. I understand it's because I'm doing contact = .... Since this is an object, I can't use push, AFAIK.
function getContact(numContacts){
contacts = {}
for (var i = 0; i < numContacts; i++){
console.log(i);
var name = faker.name.firstName() + " " + faker.name.lastName();
var phoneNum = faker.phone.phoneNumber();
var email = faker.internet.email();
contacts = {name :{ "phone number": phoneNum, "email": email}}
// contacts.name = {"phone number": phoneNum, "email":email}; // this also returns just the last instance.
};
return contacts;
};
var contacts = getContact(10); // This should create ten people, each with a phone number and email.
The loop almost successfully creates a single name. This returns:
name, 761.704.3328 x4287, Leopold81#hotmail.com
But in that iteration, name variable is actually Joe Schmoe, not literally name...
What am I overlooking to make sure that the contacts object gets populated with 10 people, with the resolved name, not just the last in the iteration?
Observations
You're trying to use name variable as key, however, what you're doing is adding a key literally called name.
What you have to do, is to create the key programmatically as follow: contacts[name] and assign the object with phoneNumber and Email.
This code is an example to simulate your scenario.
var faker = {
name: {
firstName: function() {
return "Clark";
},
lastName: function() {
return "Kent";
}
},
phone: {
phoneNumber: function() {
return '951-753-8520';
}
},
internet: {
"email": function() {
return "nothing#krypton.com";
}
}
};
function getContact(numContacts) {
var contacts = {}
for (var i = 0; i < numContacts; i++) {
var name = faker.name.firstName() + " " + faker.name.lastName();
var phoneNum = faker.phone.phoneNumber();
var email = faker.internet.email();
contacts[name + '_' + i] = {
"phone number": phoneNum,
"email": email
}
}
return contacts;
}
var contacts = getContact(10);
console.log(contacts);
The names are the keys in your object. You can use it like an array index to populate contacts. This should work:
contacts[name] = {"phone number": phoneNum, "email": email}
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));
I wanted to create small program where you enter the Book name and it's isbn code, with some other stuff, and it worked just fine until I wanted to create a prompt that asks me which book i want to delete (by it's ISBN). It actually works fine; when I write the isbn of the book that i stored in array, it deletes that book and it's isbn, but the alert is notifying me that the book does not exist in the database (not added previously) for every book I have stored.
For example, I have 5 books stored, one is (4th object in array) with "12121" ISBN code and I want to delete that one from the array. Function returns me false for first 3 objects in array (alert("Book with that ISBN doesn't exist in our database.")), then it returns true for the 4th object and then it returns me false also for the last object in array.
How do I make the function that only selects (and then deletes) object with ISBN that I put there in prompt box without checking every one of the objects inside the array?
var book = [];
book.push({
bookName: "GameOfThrones",
isbn: "12345",
});
function deleteBook(){
var book1 = prompt("Enter the ISBN of the book you want to delete");
for var(i=0; i<book.length; i++){
if (book[i].isbn == book1){
book.splice(i, 1);
alert("Book is successfully deleted");
}
else{
alert("Book with that ISBN doesn't exist in our database.");
}
}
for (var i=0; i<book.length; i++){
document.write(book[i].isbn + " - " + book[i].bookName + "<br/>");
}
}
If you choose to use an array of elements at random, then there is no getting around looking through each element. Your other option is to use a hash map or sort your array and use the binary search algorithm. Personally, I wouldn't bother with such premature optimization unless your Array is very very big (an order of a hundred thousand elements).
As an aside, your original code can be written in a much cleaner manner if you make use of the Array filter function.
var books = [];
books.push({
bookName: "GameOfThrones",
isbn: "12345",
});
var ISBNToDelete = prompt("Enter the ISBN of the book you want to delete");
function deleteBookByISBN(isbn, books) {
var newBooks = books.filter(function(book) {
return book.isbn !== isbn;
});
if (newBooks.length != books.length) {
alert("Book successfully deleted")
} else {
alert("Book with that ISBN doesn't exist in our database.");
}
return newBooks;
}
books = deleteBookByISBN(ISBNToDelete, books); // reassign the new set of books to books.
You could simply return from for statement at the moment you have found your book. The problem is when book is at the end of an array, in that case you would go trough whole array anyway.
Sorted array could help you a little bit (you would know approximately where to look for the book), but the best thing to do is to ditch the array and choose some kind of Hash table.
Easy implementation would be:
var books = {};
books['UniqueISBN'] = {name: "Where is the sun", author: "Unknown"};
Then you can delete it directly using delete;
var id = 'UniqueISBN';
delete books[id];
Easiest way with your example is to use break statement to stop processing of the for loop once you've found item:
function deleteBook(){
var book1 = prompt("Enter the ISBN of the book you want to delete");
for (var i=0,count=book.length; i<count; i++){
if (book[i].isbn == book1){
book.splice(i, 1);
alert("Book is successfully deleted");
break;
}
else{
alert("Book with that ISBN doesn't exist in our database.");
}
}
for (var i=0; i<book.length; i++){
document.write(book[i].isbn + " - " + book[i].bookName + "<br/>");
}
}
I don't know what browsers you're targeting, but if it's not IE you can eliminate the for loop and use Array.findIndex instead:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
Something like:
var index = book.findIndex(function (element) { return element.isbn == book1 });
If you filter on the array, you can return all the books that didn't match. During that process, you can store a boolean if the book was found. Using that boolean, you can perform other actions (like deleting it from the database).
You could perform those database actions inside the filter, but to keep code easier to follow and maintain, it's good to separate it. Which is why there's an if-block after the filter.
This following example demonstrates this concept above. It also uses a textarea for the logging, as opposed to the console. This is meant to serve as a demonstration on how to output to an HTML element using the textContent property.
Example:
document.addEventListener("DOMContentLoaded", onLoad);
var books = [{
bookName: "GameOfThrones",
isbn: "12345"
}, {
bookName: "Jurrasic Park",
isbn: "98765"
}, {
bookName: "Westworld",
isbn: "33333"
}];
function deleteBook(isbn) {
// use isbn passed in, or look it up
isbn = isbn || document.getElementById('isbn').value;
var book_found = false;
books = books.filter((book, i) => {
if (book.isbn == isbn) {
book_found = true;
debug.textContent += `Deleting "${book.bookName} from database...\n`;
return false;
} else
return isbn != book.isbn;
});
// handle any follow-up actions
if (book_found) {
debug.textContent += `New List (w/o ${isbn}):\n`;
outputBooks(books);
} else
debug.textContent += `Book (isnb:${isbn}) could not be found!\n\n`;
}
// Used for Logging Output (in place of console)
function outputBooks(books) {
books.forEach(book => {
debug.textContent += [' ' + book.isbn, book.bookName].join(': ') + '\n'
});
debug.textContent += '\n';
}
// Ensures the debug element is on the page
function onLoad(event) {
// Default
window.debug = document.getElementById('debug');
debug.textContent += 'Starting List:\n';
outputBooks(books);
}
textarea {
height: 20em;
width: 80%;
display: block;
}
.block {
display: block;
}
<label>ISBN:
<input id="isbn" type="text" />
</label>
<button type="button" class="delete" onclick="deleteBook()">Delete</button>
<label><span class="block">Debug:</span>
<textarea id="debug" disabled></textarea>
</label>
I don't even know if i'm using the proper terms to describe all of this, but I'm trying to use an API to make a very basic test app. That is where some of the weird words in my examples come from.
Anyway, this is what I have, and the console log returns each animal in a big list:
function listAnimals(){
animals.fetch(function(){
while(animals.hasNextEntity()) {
animal = animals.getNextEntity();
var type = animal.get('animal');
var name = animal.get('name');
var gender = animal.get('gender');
var output = 'type: '+type+', name: '+name+', gender: '+gender;
console.log(output);
}
});//fetch
}//listAnimals
However, I need to be able to access the "output" variable outside of that while loop. Placing console.log out of the while loop only returns 1 single animal:
function listAnimals(){
animals.fetch(function(){
while(animals.hasNextEntity()) {
animal = animals.getNextEntity();
var type = animal.get('animal');
var name = animal.get('name');
var gender = animal.get('gender');
var output = 'type: '+type+', name: '+name+', gender: '+gender;
}
console.log(output);
});//fetch
}//listAnimals
How do I get all "output" results outside of the while loop, and not just 1? Do I need to put it in an array first or something? How do I do that?
Yep, an array would work fine. Try something like:
function listAnimals(){
var arr = [];
animals.fetch(function(){
while(animals.hasNextEntity()) {
animal = animals.getNextEntity();
var type = animal.get('animal');
var name = animal.get('name');
var gender = animal.get('gender');
var output = 'type: '+type+', name: '+name+', gender: '+gender;
arr.push(output);
}
});//fetch
console.log(arr); // This should print out all of your outputs.
}//listAnimals