Python string/float comparison - python

I've run into the following issue, with my code below. Basically I have a list of objects with an id and a corresponding weight, and I have another list of id's. I want to use only the weights of the objects matching the id's in the second list.
d_weights = [{'d_id':'foo', 'weight': -0.7427}, ...]
d_ids = ['foo', ...]
for dtc_id in d_ids:
d_weight = next((d['weight'] for d in d_weights if d['d_id'] == dtc_id), "")
print str(d_weight)
if str(d_weight) != "":
print "not empty string! "+str(d_weight)
The output for this is:
-0.7427
0.0789
-0.0039
-0.2436
-0.0417
not empty string! -0.0417
Why is only the last one not empty when I can print them fine and they are obviously not equal to an empty string? How do I check that the next() actually returned something before using it?

You haven't correct algorithm.
So d_weight = next((d['weight'] for d in d_weights if d['d_id'] == dtc_id), "") iterate only once.
On every cycle for weight_dict in d_weights: you've got only first dict of d_weights.
Without more data, i can't reproduce your output.
In my case it works fine:
-0.7427
not empty string! -0.7427
-0.327
not empty string! -0.327
Correct code you can find in DhiaTN's answer.

just iterate of the list of the keys and get the values from each dict :
for weight_dict in d_weights
for key in d_ids:
print weight_dict.get(key, "")

Related

How to arrange arrays in a list?

I have a list of personal data(id_code,birth_year,born_in) and i want to sort the any arrays in list but i have a problem in this work.
my list data :
data = [
'id_code:3211238576;birth_year:1350;born_in:Boushehr',
'id_code:9801233575;born_in:Argentina;birth_year:1360',
'born_in:Portugal;id_code:0219206431;birth_year:1358',
'id_code:0021678913;born_in:Shiraz;birth_year:1120',
'id_code:1101102135;born_in:Gilan;birth_year:1152',
]
The code I wrote and has an bug:
for i in data:
s = ''.join(sorted(i))
print(s)
my code output:
01112233355678:::;;B___abbcddeeehhhiiinnooorrrrstuy
00112333556789:::;;A___aabbcddeeeghiiiinnnnoorrrrtty
00111223345689:::;;P___aabbcddeeghiiilnnooorrrrttuy
00011112236789:::;;S___aabbcddeehhiiiinnoorrrrtyz
00111111122355:::;;G___aabbcddeehiiiilnnnoorrrty
But! The code to i want to have in output(True answer):
id_code:3211238576,born_in:Boushehr,birth_year:1350
id_code:9801233575,born_in:Argentina,birth_year:1360
id_code:0219206431,born_in:Portugal,birth_year:1358
id_code:0021678913,born_in:Shiraz,birth_year:1120
id_code:1101102135,born_in:Gilan,birth_year:1152
Please help me to solve this problem
Assuming you want your fields to be in specific order, try this one: (I put comments in code for clarification):
data = [
'id_code:3211238576;birth_year:1350;born_in:Boushehr',
'id_code:9801233575;born_in:Argentina;birth_year:1360',
'born_in:Portugal;id_code:0219206431;birth_year:1358',
'id_code:0021678913;born_in:Shiraz;birth_year:1120',
'id_code:1101102135;born_in:Gilan;birth_year:1152',
]
def sorter(x: str):
# getting the field name
field = x.split(':')[0]
# returning it's index from "sorted_by" list
return sorted_by.index(field)
# The index of these fields will be used for sorting in "sorter" function.
sorted_by = ['id_code', 'born_in', 'birth_year']
result = []
for item in data:
# splitting the fields
splited = item.split(';')
splited.sort(key=sorter)
# building the line back and append it
result.append(';'.join(splited))
for i in result:
print(i)
output :
id_code:3211238576;born_in:Boushehr;birth_year:1350
id_code:9801233575;born_in:Argentina;birth_year:1360
id_code:0219206431;born_in:Portugal;birth_year:1358
id_code:0021678913;born_in:Shiraz;birth_year:1120
id_code:1101102135;born_in:Gilan;birth_year:1152
Now you can easily change the fields order in sorted_by list and see the result.
Try
out = [';'.join(reversed(sorted(x.split(';')))) for x in data]
print(out)
This takes every element of the data list and splits it in three strings, each of which contains one of the three attributes. Then, it arranges the three strings in reversed alphabetical order and joins them back into one string, separated by ';'

Check if a number exists in another list in python

I have two lists which contain the following type of information.
List #1:
Request = ["1/1/1.34", "1/2/1.3.5", "1/3/1.2.3", ...same format elements]
List #2:
Reply = ["1/1/0", "1/3/1", "1/2/0", ...same format elements]
From the "Reply" list, I want to be able to compare the second item in the "#/#/#", in this case it will be 1,3,2, and so on with all the items in the Reply list and check if there is a match with the second item in "Request list".
If there is a match, then I want to be able to return a new list which would contain the information of the third index in the request string appended with the third index of the matching string in the reply.
The result would be like the following.
Result = ["1.34.0", "1.3.5.0", "1.2.3.1"]
Note that the 0 was appended to the 1.34, the 1 was appended to the 1.3.4 and the 0 was appended to the 1.2.3 from the corresponding indexes in the "Reply" list as the second index existed in the "Reply" list. The 'Reply" list could have the item anywhere placed in the list.
I am unable to figure out a simple way to compare both the list one by one element for the second index. I am really confused and I would be grateful if anyone could give help me out here.
Thanks
You can also build it with list comprehension and string comparison:
res = [f"{i.split('/')[-1]}.{j.split('/')[-1]}" \
for i in Request for j in Reply \
if i.split('/')[1] == j.split('/')[1] ]
res
Out[1]:
['1.34.0', '1.3.5.0', '1.2.3.1']
You could try getting only the items you're interested in and then comparing. Something like this:
iRequest = {}
for x in Request:
iRequest[x.split('/')[1]] = x
That would give you a dictionary looking like this:
{'1':'1/1/1.34', '2':'1/2/1.35', ...and so on}
After doing the same but with the Reply list, you could go through every item in the new iReply (or whatever you choose to call it) dictionary and check if it is in iRequest. Eg:
similar = []
for x in iReply:
if x in iRequest:
similar.append(iReply[x])

Loop through dictionary keys to get values based on input

1) In my program I start with prompting a user for input.
2) I would then like to loop through the users input to get all the characters in that string, query each character individually against the dictionaries keys.
3) If a character from the input matches a key in the dictionary, I want that key's value returned.
4) This needs to be repeated for each character and the result should print those values returned in a string
To try and explain further, here is my dictionary:
dataDict = {
"a":"1",
"b":"2",
"c":"3",
}
For example:
If my input is abc, my result should be 123
If my input is cba, my result should be 321
and so on...
So far, this works if the string is only one character using the below code.
If i enter two characters, it just returns nothing.
dataInput=input("Enter stuff: ")
for key,value in dataDict.items():
if dataInput == key:
print(value)
How can I acheive the results i'm after?
You shouldn't be looping over the dict to find the matching keys, that's very inefficient. A dict is designed to do fast lookups: you give it the key and it gives you the value. Eg, dataDict["a"] results in "1".
Also, as Tim Pietzcker mentions, doing if dataInput == key will only work if dataInput consists of a single letter, because it compares the whole dataInput string to key.
Here's a simple way to do the desired conversion. We do the lookups in a list comprehension, which creates a list of the converted values, and then we pass that list to .join to create a string. (I've changed the names of your variables to conform with the PEP-008 style guide).
data_dict = {
"a": "1",
"b": "2",
"c": "3",
}
data_input = "aabbccba"
s = ''.join([data_dict[c] for c in data_input])
print(s)
output
11223321
However, that's not safe: it will fail with KeyError if data_input contains a char that's not in the dictionary. Here's a better way: it adds an empty string if it gets a bad char.
data_input = "aaxbbcycbaz"
s = ''.join([data_dict.get(c, '') for c in data_input])
print(s)
output
11223321
Alternatively, we could convert bad data to some special value, eg 0.
data_input = "aaxbbcycbaz"
s = ''.join([data_dict.get(c, '0') for c in data_input])
print(s)
output
11022303210
Just for fun, here's a "functional" version. Guido would probably not approve of this one. :)
data_input = "aaxbbcycbaz"
print(''.join(filter(None, map(data_dict.get, data_input))))
11223321
You should be iterating over the input string, not the dictionary. Also, you might want to use .get() in case the users enters a characters that's not in the dictionary:
for letter in dataInput:
print(dataDict.get(letter,"X"))
This will print each letter on its individual line. If you want to print them in a single line, you can add the end="" parameter to the print function (and print an empty line after you're done).
The comparison you're doing would never work (in the first iteration, it would amount to if "abc" == "a", I hope that makes it obvious).
You're iterating through the wrong thing. You should be iterating through the input. You don't need to iterate through the dict, because you can just look up by key.

How to dynamically append to array in dict?

This has taken me over a day of trial and error. I am trying to keep a dictionary of queries and their respective matches in a search. My problem is that there can be one or more matches. My current solution is:
match5[query_site] will already have the first match but if it finds another match it will append it using the code below.
temp5=[] #temporary variable to create array
if isinstance(match5[query_site],list): #check if already a list
temp5.extend(match5[query_site])
temp5.append(match_site)
else:
temp5.append(match5[query_site])
match5[query_site]=temp5 #add new location
That if statement is literally to prevent extend converting my str element into an array of letters. If I try to initialize the first match as a single element array I get None if I try to directly append. I feel like there should be a more pythonic method to achieve this without a temporary variable and conditional statement.
Update: Here is an example of my output when it works
5'flank: ['8_73793824', '6_133347883', '4_167491131', '18_535703', '14_48370386']
3'flank: X_11731384
There's 5 matches for my "5'flank" and only 1 match for my "3'flank".
So what about this:
if query_site not in match5: # here for the first time
match5[query_site] = [match_site]
elif isinstance(match5[query_site], str): # was already here, a single occurrence
match5[query_site] = [match5[query_site], match_site] # make it a list of strings
else: # already a list, so just append
match5[query_site].append(match_site)
I like using setdefault() for cases like this.
temp5 = match5.setdefault(query_site, [])
temp5.append(match_site)
It's sort of like get() in that it returns an existing value if the key exists but you can provide a default value. The difference is that if the key doesn't exist already setdefault inserts the default value into the dict.
This is all you need to do
if query_site not in match5:
match5[query_site] = []
temp5 = match5[query_site]
temp5.append(match_site)
You could also do
temp5 = match5.setdefault(query_site, [])
temp5.append(match_site)
Assuming match5 is a dictionary, what about this:
if query_site not in match5: # first match ever
match5[query_site] = [match_site]
else: # entry already there, just append
match5[query_site].append(temp5)
Make the entries of the dictionary to be always a list, and just append to it.

Nested dictionary behavior

I am trying to learn how to manipulate data in python.
I have the following data in a txt file
{"summonerId":000000,"games":[{"gameId":111111,"invalid":false,"gameMode":"CLASSIC","gameType":"MATCHED_GAME","subType":"NORMAL","mapId":11,"teamId":200,"championId":89,"spell1":3,"spell2":4,"level":30,"ipEarned":237,"createDate":1443314494341,"fellowPlayers":[{"summonerId":46350758,"teamId":100,"championId":157}],"stats":{"level":15,"goldEarned":10173,"numDeaths":5,"minionsKilled":48,"championsKilled":1,"goldSpent":9205,"totalDamageDealt":48752,"totalDamageTaken":23464,"team":200,"win":true,"largestMultiKill":1,"physicalDamageDealtPlayer":9064,"magicDamageDealtPlayer":35714,"physicalDamageTaken":18944,"magicDamageTaken":4005,"timePlayed":1831,"totalHeal":4129,"totalUnitsHealed":5,"assists":24,"item0":3401,"item1":2049,"item2":3117,"item3":3068,"item4":3075,"item5":1028,"item6":3340,"magicDamageDealtToChampions":9062,"physicalDamageDealtToChampions":3348,"totalDamageDealtToChampions":12411,"trueDamageDealtPlayer":3974,"trueDamageTaken":514,"wardKilled":1,"wardPlaced":16,"totalTimeCrowdControlDealt":104,"playerRole":2,"playerPosition":4}]}
My end goal is to be able to display a specific piece of information from the "stats" dictionary.
When I run the following code
import json
matches = open('testdata.txt', 'r')
output = matches.read()
data=json.loads(output)
display = data["games"]
print("Info: " + str(display))
The output is everything that corresponds to the "games" key as I would expect.
When I try
import json
matches = open('testdata.txt', 'r')
output = matches.read()
data=json.loads(output)
display = data["games"]["stats"]
print("Info: " + str(display))
I receive: TypeError: list indices must be integers, not str
I'm not really sure how to proceed given that the key is clearly a string and not an integer...
Your data["games"] value is a list; each element in that list is a dictionary, and it is those dictionaries in the list that (may) have the 'stats' key. A list can contain 0 or more elements; in this specific case there is just 1 but there could be more or none.
Loop over the list of dictionaries, or pick a specific dictionary from the list with indexing. Since there is only one in your specific example, you could just index that 1 element with the 0 index:
display = data["games"][0]["stats"]

Categories