0

I'm trying to create a dictionary (I think that's the best option...) for setting up a type of address book. The idea is to return something like

contacts = {"Bruce Wayne":{"phone number":'123-456-7890', "car":"All of them"}, "Alfred":{"phone number" :'987-654-3210', "car": "limo"}, "Clark Kent":{"phone number":'951-753-8520', "car":"None, flying works."}}

This works. I can do say console.log(contacts["Bruce Wayne"]) and it returns:

{ 'phone number': '123-456-7890', car: 'All of them' }

Doing console.log(contacts["Bruce Wayne"]["phone number"]) correctly returns

123-456-7890

However, I can't figure out how to loop through each person, and then each person's phone number and car.

Using this:

for (const[key, value] of Object.entries(contacts)){
    console.log(contacts[key]);
}

just returns

[object Object]
[object Object]
[object Object]

I'm trying to get (psuedo code)

[First key], [key] is [value], [key] is [value]

Bruce Wayne, phone number is 123-456-7890, car is All of them
Alfred, phone number is 987-654-3210, car is limo

Edit: I also tried

for (var person in contacts){
    console.log(contacts[person])
}

which also returns [object Object]...

BruceWayne
  • 22,923
  • 15
  • 65
  • 110
  • Look into `for..in`. – Rajesh Jan 24 '18 at 05:51
  • 3
    Possible duplicate of [Iterate through object properties](https://stackoverflow.com/questions/8312459/iterate-through-object-properties) – Rajesh Jan 24 '18 at 05:51
  • `var contactName, contactInfo; for(var i in contacts){ contactName = i; contactInfo = contacts[i]; }`. Of course, you have to do stuff within the loop for those vars to work like you want. – StackSlave Jan 24 '18 at 05:54
  • Consider reading that link @Rajesh provided. I happen to like using `Object.keys(myObject)`, as mentioned in the answer with the second-most votes. Brief aside: how can that question with so many votes not have an accepted answer? ;) – SimianAngel Jan 24 '18 at 05:58
  • @SimianAngel - That's what I'm playing with now (`for ... in`). And man, that post has TONS of options, I'm wading through them now... – BruceWayne Jan 24 '18 at 06:00
  • @Rajesh the issue seems to be recursion or handling "layers", not looping over object keys or entries as evident by the sample code. – stealththeninja Jan 24 '18 at 06:00
  • @stealththeninja I don't see recursion. Can you elaborate? – Rajesh Jan 24 '18 at 06:02
  • 2
    @BruceWayne The reason it gives `[object Object]` is because you have an object and console is using `.toString` method to print it. You will have to do something like `for(var key in contacts) { console.log(contacts[key]['phoneNumber']) } ` – Rajesh Jan 24 '18 at 06:05
  • @Rajesh - Ahhh, okay, I think I get it. I went with [this suggestion](https://stackoverflow.com/a/18202926/4650297) - in the loop, I have `console.log(key, contacts[key]['phone number'])` which gives the number. That'll do it for now I suppose. I'm wondering though, how to loop through each key's sub-keys. ...but that is a question for another day. Thanks for the link, took me a bit to grasp it! :D Edit: Ah! Your edit is just what I tried, cheers!! – BruceWayne Jan 24 '18 at 06:12
  • 1
    @BruceWayne Per your edit, what you're trying to `console.log` is an object. `person` is an object, so you'll need to also iterate over its properties. Something like `var message = ""; Object.keys(contacts).forEach(function(person) { message += person + ", "; var props = []; Object.keys(contacts[person]).forEach(function(key) { props.push(key + " is " + contacts[person][key]); }); message += props.join(", ") + ".\n"; }); console.log(message);` – SimianAngel Jan 24 '18 at 06:14
  • 2
    @BruceWayne to answer it in simple terms, an object is an object and methods in mentioned link will address it. So if you see, you have to recursively use the selected approach and you should be good. – Rajesh Jan 24 '18 at 06:15
  • Sorry all for the confusion - I'm new to Javascript. I naively thought just showing `console.log(...)` as a quick way to get the point across that I'm trying to just return some text. *Technically*, I'm putting this in a .ejs file and accessing via NodeJs, and trying to just loop through the values to show on my web page. (Note to self - learn the javascript semantics more!) – BruceWayne Jan 24 '18 at 06:17
  • 1
    "One-of-us! One-of-us!" :D Welcome to your new source of joy and sorrow, @BruceWayne! – SimianAngel Jan 24 '18 at 06:18
  • 1
    [FYI everyone](https://cdn-images-1.medium.com/max/455/1*snTXFElFuQLSFDnvZKJ6IA.png) :P ....but I'm getting there! Thanks to everyone for their input and advice :D – BruceWayne Jan 24 '18 at 06:20

2 Answers2

0

try this:

for (let i in contacts) {
    console.log(i + ',' + JSON.stringify(contacts[i]).replace(/\":\"/g, ' is ').replace(/["{}]/g, ''));
}

or

let contacts = { "Bruce Wayne": { "phone number": '123-456-7890', "car": "All of them" }, "Alfred": { "phone number": '987-654-3210', "car": "limo" }, "Clark Kent": { "phone number": '951-753-8520', "car": "None, flying works." } }

function consoleObj(obj, separator, attrIntro) {
    let result = '';

    for (let name in obj) {
        result += name + separator;
        for (let attr in obj[name]) {
            result += attr + attrIntro + obj[name][attr] + separator;
        }
        result += '\n';
    }

    return result;
}


console.log(consoleObj(contacts, ',', ' is '));

or this

function consoleObj(obj, separator, attrIntro) {
    return Object.keys(obj).reduce(function(result, name) {
        result += name + separator;
        Object.keys(obj[name]).forEach(function(attr) {
            result += attr + attrIntro + obj[name][attr] + separator;
        });
        result += '\n';
        return result;
    }, '');
}
console.log(consoleObj(contacts,',',' is '));
xianshenglu
  • 4,943
  • 3
  • 17
  • 34
-2

Your for..of loop is giving you the name and the object with the properties, so you need to change how you access the "phone number" and "car" to details['phone number'] etc...

const contacts = {"Bruce Wayne":{"phone number":'123-456-7890', "car":"All of them"}, "Alfred":{"phone number" :'987-654-3210', "car": "limo"}, "Clark Kent":{"phone number":'951-753-8520', "car":"None, flying works."}}

// join an object
const joinObject = (obj, glue = 'is', joiner = ', ') => 
  Object.keys(obj)
    .map(k => `${k} ${glue} ${obj[k]}`)
    .join(joiner)

// fixed string
for (const [name, details] of Object.entries(contacts)) {
  console.log(`${name}, phone number is ${details['phone number']}, car is ${details['car']}`);
}

// dynamic property description
for (const [name, details] of Object.entries(contacts)) {
  console.log(name + ' ' + joinObject(details))
}
synthet1c
  • 6,152
  • 2
  • 24
  • 39
  • 1
    Hardcoded property names! Nice! What happens if someone adds address to the object? – Nisarg Shah Jan 24 '18 at 05:56
  • @NisargShah He is parsing the data into a formatted string, what else would you propose? – synthet1c Jan 24 '18 at 05:57
  • 1
    Its a BAD practice to answer a dupe. Choose to close instead – Rajesh Jan 24 '18 at 05:58
  • 1
    @synthet1c Maybe a recursive function to get the string representation of an object of primitive properties. – Nisarg Shah Jan 24 '18 at 05:59
  • @Rajesh please explain how the answer you linked to is in anyway using ES6 `Object.entries` or a `for..of` loop. – synthet1c Jan 24 '18 at 05:59
  • @synthet1c Rajesh is correct. And even if the duplicate question doesn't use a particular method, you should post your answer there instead of here. – Nisarg Shah Jan 24 '18 at 06:02
  • @NisargShah please show an example. You are simply throwing out buzzwords without understanding what you are talking about. – synthet1c Jan 24 '18 at 06:03
  • 2
    @synthet1c First, please mind you tone. Second, object structure will always be different but the way to achieve something will remain same. We are here to show the way not code for someone. So please calm down and ask your self, is the approach similar? If not, then post your approach there. If yes, you are duplicating content and its a bad practice. Also, I guess we all have invested a lot of time on this discussion. So, I said what I had to. You can do what you want. Have a good day. :-) – Rajesh Jan 24 '18 at 06:11
  • 1
    @Rajesh imagine coming to stackoverflow with an issue. You put a lot of time into cultivating your question to make it understandable with what you have tried, what you expect and your result providing a perfect example of a question, then Rajesh comes along and doesn't provide an answer, says RTFM just to feel good about himself. I am minding my tone I have considered my response. You are toxic! – synthet1c Jan 24 '18 at 06:18
  • @synthet1c I'll be blunt. SO is not to get code solved. SO is to get your problem solved. And that is done by sharing information. If you notice, that link has solution**s**. It gives you lot many ways and also has discussion to help you with common problem. Like will your code work in IE? Answer is No. What then, should OP run again to check solution for that? A dupe is always preferred as it explains a lot more than you want and in turn, you learn something instead of just getting your problem solved. There is a reason you earn privilege with rep. – Rajesh Jan 24 '18 at 06:26