0

I have an odd problem. I am attempting to create a quote generator that has a dictionary of sections of a quote (each value is a list), pulls a random item from that list for each key and appends that to another list. That list will then be printed to show the final quote.

However, I am getting the quote's sections in a random order. When running, I get something like this:

['avoid ', 'hobby.', "it's easy to ", 'your ', 'Occasionally ', 'most important ']

Here's my code:

from random import choice

quoteWords = {
    "one": ["Sometimes ", "Often ", "Occasionally ", "Usually "],
    "two": ["it's best to ", "you should ", "you shouldn't ", "it's easy to ", "it's hard to "],
    "three": ["do ", "avoid ", "finish", "create ", "witness "],
    "four": ["the ", "a ", "your ", "society's ", "your friends' ", "the government's "],
    "five": ["best ", "most important ", "funniest "],
    "six": ["work.", "art.", "hobby.", "posessions."],
}

def inspire():
    quote = []
    counter = 0
    for key in quoteWords:
        quote.insert(counter, choice(quoteWords[key]))
        counter += 1
    return(quote)

print(inspire())

Any help would be greatly appreciated. Thanks in advance!

3 Answers3

1

Dictionaries don't have order.

for key in quoteWords has no guaranteed order in which the keys will be returned.

You should use an OrderedDict:

from random import choice
from collections import OrderedDict

quoteWords = OrderedDict()

quoteWords['one'] = ["Sometimes ", "Often ", "Occasionally ", "Usually "]
quoteWords['two'] = ["it's best to ", "you should ", "you shouldn't ", "it's easy to ", "it's hard to "]
quoteWords['three'] = ["do ", "avoid ", "finish", "create ", "witness "]
quoteWords['four'] = ["the ", "a ", "your ", "society's ", "your friends' ", "the government's "]
quoteWords['five'] = ["best ", "most important ", "funniest "]
quoteWords['six'] = ["work.", "art.", "hobby.", "posessions."]

# or create directly from list of tuples as in @schwobaseggl's answer.

def inspire():
    quote = []
    counter = 0
    for key in quoteWords:

        quote.insert(counter, choice(quoteWords[key]))
        counter += 1
    return(quote)
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
0

You can use an OrderedDict! In a common dict there is no guarantee about the keys' or items' order:

from collections import OrderedDict
quoteWords = OrderedDict([
    ("one", ["Sometimes ", "Often ", "Occasionally ", "Usually "]),
    ("two", ["it's best to ", "you should ", "you shouldn't ", "it's easy to ", "it's hard to "]),
    ("three", ["do ", "avoid ", "finish", "create ", "witness "]),
    ("four", ["the ", "a ", "your ", "society's ", "your friends' ", "the government's "]),
    ("five", ["best ", "most important ", "funniest "]),
    ("six", ["work.", "art.", "hobby.", "posessions."]),
])
# ...
print(''.join(inspire()))
Usually you should witness the best work. 

The way you are using it, you don't even need a mapping. You could just use a list of lists and pick one item from each.

user2390182
  • 72,016
  • 6
  • 67
  • 89
0

I guess you are using Python2. In Python, the dict is not ordered though your code runs correctly in Python3 (thanks @schwobaseggl):

(ins)>>> quoteWords = {
(ins)...     "one": ["Sometimes ", "Often ", "Occasionally ", "Usually "],
(ins)...     "two": ["it's best to ", "you should ", "you shouldn't ", "it's easy to ", "it's hard to "],
(ins)...     "three": ["do ", "avoid ", "finish", "create ", "witness "],
(ins)...     "four": ["the ", "a ", "your ", "society's ", "your friends' ", "the government's "],
(ins)...     "five": ["best ", "most important ", "funniest "],
(ins)...     "six": ["work.", "art.", "hobby.", "posessions."],
(ins)... }
(ins)>>> quoteWords
{'six': ['work.', 'art.', 'hobby.', 'posessions.'], 'three': ['do ', 'avoid ', 'finish', 'create ', 'witness '], 'two': ["it's best to ", 'you should ', "you shouldn't ", "it's easy to ", "it's hard to "], 'four': ['the ', 'a ', 'your ', "society's ", "your friends' ", "the government's "], 'five': ['best ', 'most important ', 'funniest '], 'one': ['Sometimes ', 'Often ', 'Occasionally ', 'Usually ']}

Simply use list to solve the problem. What's more, using append is more convenient than insert:

from random import choice

quoteWords = [
    ["Sometimes ", "Often ", "Occasionally ", "Usually "],
    ["it's best to ", "you should ", "you shouldn't ", "it's easy to ", "it's hard to "],
    ["do ", "avoid ", "finish", "create ", "witness "],
    ["the ", "a ", "your ", "society's ", "your friends' ", "the government's "],
    ["best ", "most important ", "funniest "],
    ["work.", "art.", "hobby.", "posessions."],
]

def inspire():
    quote = []
    for choices in quoteWords:
        quote.append(choice(choices))
    return(quote)

print(inspire())
zsrkmyn
  • 547
  • 1
  • 5
  • 20
  • Ähh, and in Python-3, a `dict` is ordered?!? – user2390182 Feb 26 '17 at 09:37
  • @schwobaseggl, I am not sure. but I test the codes with Python3 and it runs correctly. – zsrkmyn Feb 26 '17 at 09:39
  • 1
    Yup, that might well be. But just like in Python-2.x, dicts are unordered! And as in Python-2.x, for some keys, depending on their hashes, the order might not seem entirely random. That does not mean you can rely on that. – user2390182 Feb 26 '17 at 09:43