Using next instead of break in comprehension list - python

Considering a word, I'd like to search it in a dictionary, first as key and then as value.
I implemented in the following way:
substitution_dict={'land':['build','construct','land'],
'develop':['develop', 'builder','land']}
word='land'
key = ''.join([next(key for key, value in substitution_dict.items() if word == key or word in value)])
The idea is to take advantage of short-circuiting, the word is first compare with the key, else with the value. However, I'd like to stop when is found in the key.
Running the above snippet works good. However, when the word changes to other word not present in the dictionary, it throws StopIteration error due to the next statement which is not finding results.
I was wondering if this is doable in one line as I intended.
Thanks

You could pass a default argument in next().And next() would only return only one element,so "".join([]) is unnecessary.
Code below:
key = next((key for key, value in substitution_dict.items() if word == key or word in value), None)
When the iterator is exhausted, it would return None.
Or if you really want to use it with ''.join, like:
key = "".join([next((key for key, value in substitution_dict.items() if word == key or word in value), "")])

Related

How to get the key element based on matching the key element in a dictionary?

I have a dictionary which looks like this:
dictionary={
"ABC-6m-RF-200605-1352": "s3://blabla1.com",
"ABC-3m-RF-200605-1352": "s3://blabla2.com",
"DEF-6m-RF-200605-1352": "s3://blabla3.com"
}
Now, I want to do a matching which takes input such as helper="ABC-6m" and tries to match this string to the key of the dictionary and returns the key (not the value)!
My code currently looks like this but it is not robust, i.e. sometimes it works and sometimes it does not:
dictionary_scan = dict((el, el[:7]) for el in dictionary)
#swapping key and value
dictionary_scan = dict((v, k) for k, v in dictionary.items())
#concat string components in helper variable
helper = 'ABC'+'-'+'6m'
out=list(value for key, value in dictionary_scan.items() if helper in key)
The expected output is: 'ABC-6m-RF-200605-1352'. Sometimes this works in my code but sometimes it does not. Is there a better and more robust way to do this?
If you make a dictionary that maps prefixes to full keys, you'll only be able to get one key with a given prefix.
If there can be multiple keys that start with helper, you need to check them all with an ordinary list comprehension.
out = [key for key in dictionary if key.startswith(helper)]

Read json key value as insensitive key

I need to be able to pull the value of the key 'irr' from this json address in python:
IRR = conparameters['components'][i]['envelope'][j]['irr']
Even if 'irr' is any oher case, like IRR, Irr... etc.
Is that easy?
There's nothing built-in that does it, you have to search for a matching key.
See Get the first item from an iterable that matches a condition for how to write a first() function that finds the first element of an iterable that matches a condition. I'll use that in the solution below.
cur = conparameters['components'][i]['envelope'][j]
key = first(cur.keys(), lambda k: lower(k) == 'irr')
IRR = cur[key]

python dictionary: value and the key not corresponding in my code to find max

My goal is to figure out who has the most message the file is here.mbox-short.txt.
My code is here.
fhand = open('mbox-short.txt')
counts = dict()
#this loop is to creat a dictionary in which key is the mail's name
#value is times the mail's name appeared
for line in fhand:
if not (line.startswith('From')and not line.startswith('From:')):
continue
words = line.split()
counts[words[1]] = counts.get(words[1],0) + 1
num = None
#this loop is to find max value and its key
for key, value in counts.items():
#print key, value
if num == None or counts[key] > num:
num = counts[key]
print key, num.
After I ran the code. The result is:
But when I run the line print key,value in the second loop, comment the line which under the print key, value, the result is show that the ray#media.berkeley.edu is 1 instead of 5. The cwen#input.edu is 5.
So why the key and value is not corresponding. I thin the problem is on line 19. How can solve it?
It seemly that I didn't save the key.
Thank you for all.
Thank all of you. I solved it.
In the second loop, I created a variable to save the key
I’m not sure if i understand what you want to do. The fist loop should count all address and the second should find the maximum?
You have to inialize num with some value, but I would choose zero. Then you haven’t check for num == None. And you muss save the key, not only the value. The key will always be the last key in the dict.
You need to use the Counter class, its designed for this exact purpose:
import re
from collections import Counter
with open('mbox-short.txt') as f:
emails = Counter([i.strip() for i in re.findall(r'From:(.*?)', f.read(), re.M)])
for email, count in emails.most_common():
print('{} - {}'.format(email, count))
As you realized you need to store the key which gives the max value, or at least max-value-so-far. Then you don't need to store num, the maximum counts[key] value so far, only the key that gives it max_key.
Also, you iterate on the items in counts with for key, value in counts: ..., but then you ignore value inside the loop. Use value; there's no need to look up counts[key] again. And as long as counts has >=1 item, you don't need the pessimism of setting num = None and then testing against that inside your loop. Anyway, num is unnecessary.
# Iterative approach
max_key = counts.keys()[0] # default assumption
for key, value in counts.items():
if value > counts[max_key]:
max_key = key
but you can avoid all this by directly finding the max without needing to iterate:
# Direct approach, using `max(..., key=...)`
max_key = max(counts, key=lambda kv: kv[1])
print max_key, counts[max_key]
cwen#iupui.edu 5
This works because Python sorted(), max(), min() will accept a dictionary, and they have an optional parameter key which allows you to pass in a function telling the comparison which element in each item to use.
Look at the doc for sorted(), max(), min(), and read about Python idioms using them.
There is also the custom collections.Counter which #Burhan references. But it's important to learn how to sort things first. Then you can use it.

How to compare array entries to dictionary keys and return a dictionary value

I am trying to make a python program that takes user input text or a file and changes each character into a value and then returns the result.
I have a user string that being read into a list.
I am trying to have a for loop go through that list and check each character against a dictionary key and then return the value in the dictionary. How would i go about doing that?
Thanks
Code so far:
for i in range (0, len(text)):
for j in alphabet.keys():
if text[i].upper() == alphabet.values():
j+=1
print(alphabet.items())
i+=1
for item in list_:
try:
print(d[item])
except KeyError as e:
print("{} not in d".format(e.args[0]))
Without seeing your code, I can't offer anything more relevant
You probably want to use string.maketrans and string.translate
>>> import string
>>> table = string.maketrans('abc', 'xyz')
>>> string.translate('the cat is bad', table)
'the zxt is yxd'
Most of the code below is simply to create the dictionary that translates letters of an input into randomised corresponding values in a dict (i.e. each letter maps to another random letter). Points on your code:
1) range() automatically defaults to starting at 0 so range(0, n) is better just written as range(n)
2) You don't need to use range() at all here. for letter in string will take an input string and go through it, letter by letter. for elephant in string will do the same, each letter is being assigned to the name elephant in turn, so the fact that I chose to use letter instead is simply for readability.
3) Using keys(), values() and items() is not the way to query a dictionary. You have two standard approaches; I could use translation_dict[letter] which will throw KeyError if the value of letter is not a key in the dictionary, or translation_dict.get(letter) which will return None if the key doesn't exist. In the below example, I used get() but also added another parameter ("not in dict") which replaces None as the default value if the letter isn't found as a key.
import string # For setup of example data
import random # For setup of example data
# Just creating the translation dictionary and fake user input
alphabet = list(string.uppercase)
translated = random.sample(alphabet, len(alphabet))
translation_dict = {i: j for i, j in zip(alphabet, translated)}
user_input = 'Hello'
# The loop you're trying
for letter in user_input:
corresponding_value = translation_dict.get(letter.upper(), 'Not in dict')
print(corresponding_value)

Check if Dictionary Values exist in a another Dictionary in Python

I am trying to compare values from 2 Dictionaries in Python. I want to know if a value from one Dictionary exists anywhere in another Dictionary. Here is what i have so far. If it exists I want to return True, else False.
The code I have is close, but not working right.
I'm using VS2012 with Python Plugin
I'm passing both Dictionary items into the functions.
def NameExists(best_guess, line):
return all (line in best_guess.values() #Getting Generator Exit Error here on values
for value in line['full name'])
Also, I want to see if there are duplicates within best_guess itself.
def CheckDuplicates(best_guess, line):
if len(set(best_guess.values())) != len(best_guess):
return True
else:
return False
As error is about generator exit, I guess you use python 3.x. So best_guess.values() is a generator, which exhaust for the first value in line['full name'] for which a match will not be found.
Also, I guess all usage is incorrect, if you look for any value to exist (not sure, from which one dictinary though).
You can use something like follows, providing line is the second dictionary:
def NameExists(best_guess, line):
vals = set(best_guess.values())
return bool(set(line.values()).intersection(vals))
The syntax in NameExists seems wrong, you aren't using the value and best_guess.values() is returning an iterator, so in will only work once, unless we convert it to a list or a set (you are using Python 3.x, aren't you?). I believe this is what you meant:
def NameExists(best_guess, line):
vals = set(best_guess.values())
return all(value in vals for value in line['full name'])
And the CheckDuplicates function can be written in a shorter way like this:
def CheckDuplicates(best_guess, line):
return len(set(best_guess.values())) != len(best_guess)

Categories

Resources