Python Forum
General Programming Question with Dictionary
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
General Programming Question with Dictionary
#1
I have a dictionary that contains books names, numbers of pages, who wrote the book, etc. What I attempting to do is search the whole dictionary for all the numbers for example 1,56,54 and even numbers as such 1894-3999 RT and replace/update them with the spelling of the numbers.
I came up with the following after trying different combinations :
value  = re.findall(r'[0-9]+', str(cybc)) #Find all the numbers in dictionary
for t in value: #Loop through Values
    cybc.update(num2words(int(t))) #Update Dictionary with new values
    print('With Words',num2words(int(t))) # Print the spelled out words
However when ran I get the following error message:
ValueError: dictionary update sequence element #0 has length 1; 2 is required
What are the final steps to finish this? As I know there is something small to finish it but I cannot seem to figure it out. Thanks.
Reply
#2
A dictionary is a set of key/value pairs. You have to tell the dictionary which key you are trying to update. Your program just shoves a new value at it.

But assuming cybc is your dictionary, then str(cybc) is just a big string of all the keys and values (and some punctuation) smushed together. So when you're handed a string, you can't tell what part of the dictionary it came from.

If the key has digits in it, do you want to change the key, or do you just want to change the values?
Reply
#3
(Jan-07-2022, 06:08 AM)bowlofred Wrote: A dictionary is a set of key/value pairs. You have to tell the dictionary which key you are trying to update. Your program just shoves a new value at it.

But assuming cybc is your dictionary, then str(cybc) is just a big string of all the keys and values (and some punctuation) smushed together. So when you're handed a string, you can't tell what part of the dictionary it came from.

If the key has digits in it, do you want to change the key, or do you just want to change the values?

Oh Ok I see I am trying to figure that one out right now to only change the values only.
Reply
#4
Then the right way to do this is to grab each of the key/value pairs, examine the value and if it needs changing, update it by setting the key to have a new value.

for key, value in cybc.items():
    # evaluate/change the value
    cybc[key] = updated_value(value) # updated_value() needs to return the correct value for your update
The other concern I have is that the value might have a part of a number in it, but your current technique would throw away all the non-number parts. Is that what you want? Or it might have multiple numbers. Let's say one of your values is the string "1894-3999 RT". What do you want the new value to be? It can't be two integers. It could be one of the integers, or it could be a list or a tuple with both integers, or... ?
Reply
#5
(Jan-07-2022, 07:54 AM)bowlofred Wrote: Then the right way to do this is to grab each of the key/value pairs, examine the value and if it needs changing, update it by setting the key to have a new value.

for key, value in cybc.items():
    # evaluate/change the value
    cybc[key] = updated_value(value) # updated_value() needs to return the correct value for your update
The other concern I have is that the value might have a part of a number in it, but your current technique would throw away all the non-number parts. Is that what you want? Or it might have multiple numbers. Let's say one of your values is the string "1894-3999 RT". What do you want the new value to be? It can't be two integers. It could be one of the integers, or it could be a list or a tuple with both integers, or... ?

Thanks for the information and insight. What I seeking is to look through all the values and if it has a digit for example 1,5,56 or in strings like "1894-3999 RT" , "They are 75 Artist 2 pending" update the values to one, five, fifty-six and in the strings "one thousand, eight hundred and ninety-four-three thousand, nine hundred and ninety-nine RT" and "They are seventy-five Artist two pending". Thanks
Reply
#6
So you'll need to create a parser for that, and I'm not sure it will be easy unless you already know your input will be restricted to certain types. Here's a couple of items that might be challenging to distinguish:

"The car was priced at $52,400."
"I've got red, green, and blue, with 100,200, and 75 respectively"

You might take a look at https://pypi.org/project/inflect/. It can turn numbers (or strings of digits) into english terms (assuming you've already parsed the correct number).

>>> import inflect
>>> p = inflect.engine()
>>> p.number_to_words(52400)
'fifty-two thousand, four hundred'
>>> p.number_to_words("52400")
'fifty-two thousand, four hundred'
Reply
#7
(Jan-07-2022, 07:01 PM)bowlofred Wrote: So you'll need to create a parser for that, and I'm not sure it will be easy unless you already know your input will be restricted to certain types. Here's a couple of items that might be challenging to distinguish:

"The car was priced at $52,400."
"I've got red, green, and blue, with 100,200, and 75 respectively"

You might take a look at https://pypi.org/project/inflect/. It can turn numbers (or strings of digits) into english terms (assuming you've already parsed the correct number).

>>> import inflect
>>> p = inflect.engine()
>>> p.number_to_words(52400)
'fifty-two thousand, four hundred'
>>> p.number_to_words("52400")
'fifty-two thousand, four hundred'

Oh here is the updated code information:

from num2words import num2words

cybc = {col[0]: col[1:] for col in zip(*sheet.values) }

for key, value in cybc.items():
    if value == re.findall(r'[0-9]+', str(cybc)):
          cybc[key] = re.sub(r"[0-9]+",  num2words(int(value)) ,str(cybc))
          print('Test to show updated value', value)
          print('Test to show keys', key)
I just ran the code but it does not print anything and I just remembered that the only key that do not want modified is the key Book Names all others can be changed.
Reply
#8
Line 6 won't work. You're asking if the current value is a match object. I presume that your current values are strings, so that won't ever succeed.

You're using "findall", but findall only hands you the bits that match, not the non-digit bits (which you presumably want to retain). Possibly you want to use re.sub instead. Then if your num2words can take a match object instead of an int, you could write it as:

sub match2words(m):
    digits = m.group()
    # convert this with whatever means you have
    return "converted"

for key, value in cybc.items():
    new_value = re.sub(r'\d+', match2words, value)
    cybc[key] = new_value
    print('Test to show updated value', new_value)
    print('Test to show keys', key)
Reply
#9
Can you post your an excerpt from your dictionary, maybe 3 or 4 key:value pairs?

That would make things clearer for me.
Reply
#10
(Jan-07-2022, 10:57 PM)Pedroski55 Wrote: Can you post your an excerpt from your dictionary, maybe 3 or 4 key:value pairs?

That would make things clearer for me.

Please see below:
for key, value in cybc.items():
    print('Key',key, '->', 'Value',value ,'\n')
 
Key BookNumber -> Value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Key Book Names -> Value ('For Whom the Bell Tolls', 'Brave New World', 'Nineteen Eighty-Four', 'The Sound and the Fury', 'Gone with the Wind', "Lady Chatterley's Lover", 'The Hound of the Baskervilles', 'I Am Number 4', 'The Great Gatsby', 'The War of the Worlds', 'The Lord of the Rings', 'Martin Eden', 'On the Road', "A Room of One's Own", 'Lord Jim', 'Manhattan Transfer', "Sophie's Choice", 'The Catcher in the Rye', 'No Orchids For Miss Blandish', 'The Origins of Totalitarianism The Burden of Our Time', 'Fahrenheit 451')
Key Pages -> Value (None, 311, 328, 326, '1037 (first edition), 1024 (Warner Books Paperback)', None, None, 440, None, 287, 'original manuscripts, which total 9,250 pages', None, 320, 172, None, None, 562, 234, None, 704, 256)
Key Written Time/Published -> Value (1940, 1932, 1949, 1929, 1936, 1928, '1901–02', 2009, 1925, 1898, '1954–55', 1909, 1957, 1929, 1900, 1925, 1979, 1951, 1939, 1951, 1953)
Key Authors -> Value ('Ernest Hemingway', 'Aldous Huxley', 'George Orwell', 'William Faulkner', 'Margaret Mitchell', 'D.H. Lawrence', 'Arthur Conan Doyle', 'Jobie Hughes, James Frey', 'F. Scott Fitzgerald', 'H.G. Wells', 'J.R.R. Tolkien', 'Jack London', 'Jack Kerouac', 'Virginia Woolf', 'Joseph Conrad', 'John Dos Passos', 'William Styron', 'J.D. Salinger', 'James Hadley Chase', 'Hannah Arendt', 'Ray Bradbury')
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  python can - general question caslor 0 1,094 Jul-14-2022, 05:21 PM
Last Post: caslor
  a general question barryjo 5 1,442 Feb-01-2022, 10:12 PM
Last Post: Gribouillis
Big Grin General programming question (input string)[ jamie_01 2 1,568 Jan-08-2022, 12:59 AM
Last Post: BashBedlam
  Question about formula implementation in general format Alienspecimen 0 1,633 Mar-01-2021, 08:39 PM
Last Post: Alienspecimen
  General list size question to solve problem Milfredo 3 2,319 Sep-27-2020, 08:42 AM
Last Post: Milfredo
  New to programming, loop question tomyan 1 1,588 Sep-25-2020, 04:32 PM
Last Post: Larz60+
  General Listbox question. Milfredo 4 2,096 Sep-06-2020, 07:36 PM
Last Post: Milfredo
  Dictionary question DrZ 2 1,619 Jul-29-2020, 08:53 PM
Last Post: DrZ
  General question about serialization/deserialization in python local 1 1,797 Jan-28-2020, 04:35 AM
Last Post: Larz60+
  General Programming Question Qui_Ten 1 2,144 Jan-14-2019, 11:15 AM
Last Post: steve_shambles

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020