I am trying to make a function that will take elements and values input by the user, and list whichever element has the highest value. For example,
['H', 14.5, 'Be', 2.5, 'C', 50.5, 'O', 22.5 'Mg', 4.0, 'Si', 6.0]
the correct answer is 'C'. I can't seem to figure out how to get this to work. I don't have any code yet, unfortunately.
You can zip the list with itself to get alternating tuples. If you put the number first, you can just use max() to get the largest. This assumes there are not ties:
l = ['H', 14.5, 'Be', 2.5, 'C', 50.5, 'O', 22.5, 'Mg', 4.0, 'Si', 6.0]
num, symbol = max(zip(l[1::2], l[::2]))
# (50.5, 'C')
This works because tuples are compared in order and zipping alternating values gives a collection of tuples like:
list(zip(l[1::2], l[::2]))
# [(14.5, 'H'), (2.5, 'Be'), (50.5, 'C'), (22.5, 'O'), (4.0, 'Mg'), (6.0, 'Si')]
Given:
li=['H', 14.5, 'Be', 2.5, 'C', 50.5, 'O', 22.5, 'Mg', 4.0, 'Si', 6.0]
Create tuples and then take max of those tuples:
>>> max(((li[i],li[i+1]) for i in range(0,len(li),2)), key=lambda t: t[1])
('C', 50.5)
Welcome to StackOverflow!
As far as I understand your question, you try to find a maximum element in a list that contains both strings (e.g., 'C') as keys and numbers (e.g., '50.5') as values. For this purpose, a dictionary is more convenient:
dictionary = {'H': 14.5, 'Be': 2.5, 'C': 50.5, 'O': 22.5, 'Mg': 4.0, 'Si': 6.0}
max_key = max(dictionary, key=dictionary.get)
print(max_key)
# 'C'
I hope it helps.
Assuming that each numerical value is positive:
lst = ['H', 14.5, 'Be', 2.5, 'C', 50.5, 'O', 22.5, 'Mg', 4.0, 'Si', 6.0]
index, _ = max(enumerate(lst), key=lambda p: p[1] if isinstance(p[1], float) else 0)
el = lst[index-1]
print(el)
otherwise first filter by type and then get the index of the maximal value
_, index = max(((v, i) for i, v in enumerate(lst) if isinstance(v, float)))
el = lst[index-1]
print(el)
Related
As mentioned in the question, I have a list like this:
l = ['a', 'a', 'a', 200.0, 1.0, -55.4, 6.5, 'b', 'b', 'b']
and I want to get the minimum and the maximum values from that list in order to replace the strings 'a' with the minimum and 'b' with the maximum.
My output has to be like this:
l = [-55.4, -55.4, -55.4, 200.0, 1.0, -55.4, 6.5, 200.0, 200.0, 200.0]
I am able to achieve this goal by using a while loop to create another list to store only the numeric values, then sort this new list and pass the minimum value (as the 0th element of this new list) to a variable and the max (as the last element) to another variable.
Since my list contains many more elements than the one I wrote as example, I'd like to know if there's a more efficient way to do this.
Thanks a lot :)
l = ["a", "a", "a", 200.0, 1.0, -55.4, 6.5, "b", "b", "b"]
mx = max((v for v in l if isinstance(v, float)))
mn = min((v for v in l if isinstance(v, float)))
out = [{"a": mn, "b": mx}.get(v, v) for v in l]
print(out)
Prints:
[-55.4, -55.4, -55.4, 200.0, 1.0, -55.4, 6.5, 200.0, 200.0, 200.0]
I have a list of coordinates and another list of height values. How can I append height values to coordinate list in sequential order?
coor = [[[83.75, 18.70], [57.50, 18.70], [57.5, 2.87], [83.75, 4.18]],
[[83.75, 34.54], [110.0, 35.0], [104.86, 19.59], [83.75, 19.59]],
[[104.86, 19.59], [83.75, 19.59], [83.75, 4.18], [100.0, 5.0]],
[[-5.0, 33.0], [18.12, 33.40],[18.12, 16.70],[-2.53, 16.70]],
[[18.12, 16.70],[-2.53, 16.70], [0.0, 0.0],[18.12, 0.90]]]
height = [5,4,5,6,6]
expected result:
result = [[[83.75, 18.70], [57.50, 18.70], [57.5, 2.87], [83.75, 4.18],5],
[[83.75, 34.54], [110.0, 35.0], [104.86, 19.59], [83.75, 19.59],4],
[[104.86, 19.59], [83.75, 19.59], [83.75, 4.18], [100.0, 5.0],5],
[[-5.0, 33.0], [18.12, 33.40],[18.12, 16.70],[-2.53, 16.70],6],
[[18.12, 16.70],[-2.53, 16.70], [0.0, 0.0],[18.12, 0.90],6]]
If you don't mind tuples, you can just use zip
> list(zip(coor, height))
[([[83.75, 18.7], [57.5, 18.7], [57.5, 2.87], [83.75, 4.18]], 5),
([[83.75, 34.54], [110.0, 35.0], [104.86, 19.59], [83.75, 19.59]], 4),
...
If it must be a list use zip in a comprehension.
> [list(pair) for pair in zip(coor, height)]
[[[83.75, 18.7], [57.5, 18.7], [57.5, 2.87], [83.75, 4.18]], 5],
[[[83.75, 34.54], [110.0, 35.0], [104.86, 19.59], [83.75, 19.59]], 4],
...
tldr: One line solution, zip the iterables (Python docs) and list for desired output explanation below:
[list(item) for item in list(zip(coor,height))]
explanation:
list1 = [
[['a','a'],['aa','aa']],
[['b','b'],['bb','bb']]]
list2 = [1,2]
for item in list(zip(list1,list2)):
print('zip output', item)
print('desired output', list(item))
Output:
zip output ([['a', 'a'], ['aa', 'aa']], 1)
desired output [[['a', 'a'], ['aa', 'aa']], 1]
zip output ([['b', 'b'], ['bb', 'bb']], 2)
desired output [[['b', 'b'], ['bb', 'bb']], 2]
as one line list comprehension :
[list(item) for item in list(zip(list1,list2))]
Output:
[[[['a', 'a'], ['aa', 'aa']], 1], [[['b', 'b'], ['bb', 'bb']], 2]]
without any imports
# given
deps = {'W': ['R', 'S'], 'C': [], 'S': ['C'], 'R': ['C'], 'F': ['W']}
prob = {'C': [0.5], 'R': [0.2, 0.8], 'S': [0.5, 0.1], 'W': [0.01, 0.9, 0.9, 0.99], 'F' : [0.4, 0.3]}
k = 'F'
# want to return: L = [[0.2, 0.8], [0.5, 0.1], [0.01, 0.9, 0.9, 0.99], [0.4, 0.3]]
# attempt
L = []
for i in deps[k]:
s = i
while(deps[s] != []):
L.append(prob[s])
s = deps[s]
print(L)
I'm having trouble figuring this out. So given 2 dictionaries: dependents and probability I wish to traverse through a select point and set every value so for the above example I chose 'F'.
It would first go into the deps of 'F', find 'W' and then check the deps of that being ['R', 'S'] then check 'R' seeing that the depedent of 'R' is 'C' and 'C' does not a depedent so we stop at 'R' and append its probability into L.
[[0.2, 0.8]]
then we go into S and do the same thing
[[0.2, 0.8], [0.5, 0.1]]
then we're done with that and we're back at W
[[0.2, 0.8], [0.5, 0.1], [0.01, 0.9, 0.9, 0.99]]
and finally since we're done with W we get the prob dict of F
[[0.2, 0.8], [0.5, 0.1], [0.01, 0.9, 0.9, 0.99], [0.4, 0.3]]
My code fails when theres more than one dependent value. Not sure how to wrap my head around that. Trying to make a function that will do this given deps and prob and value of k
I would solve the problem with a while loop that keeps looking to see if you've used all the values you've recursively found. You can use a structure like:
deps = {'W': ['R', 'S'], 'C': [], 'S': ['C'], 'R': ['C'], 'F': ['W']}
# out = ['F', 'W', 'R', 'S']
prob = {'C': [0.5], 'R': [0.2, 0.8], 'S': [0.5, 0.1], 'W': [0.01, 0.9, 0.9, 0.99], 'F': [0.4, 0.3]}
k = 'F'
L = []
my_list = []
found_all = False
def get_values(dep_dictionary, prob_dict, start_key):
used_keys = []
keys_to_use = [start_key]
probability = []
# build a list of linked values from deps dictionary
while used_keys != keys_to_use:
print('used: {}'.format(used_keys))
print('to use: {}'.format(keys_to_use))
for i in range(len(keys_to_use)):
if keys_to_use[i] not in used_keys:
new_keys = dep_dictionary[keys_to_use[i]]
if len(new_keys):
for sub_key in new_keys:
if sub_key not in keys_to_use:
keys_to_use.append(sub_key)
used_keys.append(keys_to_use[i])
else:
del keys_to_use[i]
# at this point used_keys = ['F', 'W', 'R', 'S']
for key in used_keys:
probability.append(prob_dict[key])
print(probability)
get_values(deps, prob, k)
Which outputs:
used: []
to use: ['F']
used: ['F']
to use: ['F', 'W']
used: ['F', 'W']
to use: ['F', 'W', 'R', 'S']
used: ['F', 'W', 'R', 'S']
to use: ['F', 'W', 'R', 'S', 'C']
[[0.4, 0.3], [0.01, 0.9, 0.9, 0.99], [0.2, 0.8], [0.5, 0.1]]
Where you can see the output is correct ([[0.4, 0.3], [0.01, 0.9, 0.9, 0.99], [0.2, 0.8], [0.5, 0.1]]), however it is not in the exact same order, but it doesn't sound like that should be a huge issue. If it is, you can always re-splice it into a dictionary by adjusting the
for key in used_keys:
probability.append(prob_dict[key])
bit such that probability is a dictionary also. You can also take the print() statements out, they were just there to debug and show visually what is going on within the loop. You also would probably have the function return probability instead of printing it, but I'll leave that to your discretion!
Here is a solution that uses a stack-based depth-first search to traverse the dependency tree. It adds probabilities at each step iff. the node has dependencies, and then simply reverses the list at the end.
def prob_list(root):
nodes_to_visit = [root]
prob_list = []
while nodes_to_visit:
curr = nodes_to_visit.pop()
print(f"Visiting {curr}")
if deps[curr]:
prob_list.append(prob[curr])
for dep in deps[curr]:
nodes_to_visit.append(dep)
return list(reversed(prob_list))
print(prob_list("F")) # [[0.2, 0.8], [0.5, 0.1], [0.01, 0.9, 0.9, 0.99], [0.4, 0.3]]
I have four lists representing X and Y coordinates of different points in lists A and B so X_A, Y_A, X_B, Y_B
A ] ['a', 'b', 'c', 'd', 'e', 'f']
X_A = [1.0, 2.2, 3.0, 4.0, 5.001, 6.0]
Y_A = [0.0, 2.0, 4.0, 6.1, 8.0, 0.0]
B = ['k', 'l', 'm', 'n', 'o', 'p']
X_B = [1.0, 3.0, 5.0005, 7.0, 9.1, 11.0]
Y_B = [0.0, 1.0, 8.0, 2.0, 8.0, 0.1]
The above is read as 'a' has coordinates (1.0, 0.0) and 'l' has coordinates (3.0, 1.0)
I would like to add items from A to Node_A list and items from B to Node_B the corresponding coordinates of the elements of lists A and B satisfy an error margin:
(X_A - X_B) <= error and (Y_A - Y_B) <= error
I have the below code which I believe should be doing the job but it does not seem to work and I don't understand why, any help is appreciated!
Node_A, Node_B = [], []
error = 1e-2
i, j = 0, 0
for lo1,la1 in zip(X_A, Y_A):
for lo2,la2 in zip(X_B, Y_B):
if abs(lo1 - lo2) <= error and abs(la1 == la2) <= error:
Node_A.append(A[i])
Node_B.append(B[j])
break
j += 1
i += 1
j = 0
The desired output should be as below as they 'a' coordinates from A equal 'k' coordinates from B and 'e' coordinates satisfy the error margin and thus approximately equal to 'm' coordinates:
Node_A: ['a', 'e']
Node_B: ['k', 'm']
Instead I get Node_A: ['c'] and Node_B: ['l']
Change
if abs(lo1 - lo2) <= error and abs(la1 == la2) <= error:
to
if abs(lo1 - lo2) <= error and abs(la1 - la2) <= error:
Result:
['a', 'e']
['k', 'm']
You made a typo in the second condition.
This gives you a:e,k:m:
i, j = 0, 0
for lo1,la1 in zip(X_A, Y_A):
for lo2,la2 in zip(X_B, Y_B):
if abs(lo1 - lo2) <= error and abs(la1 - la2) <= error:
Node_A.append(A[i])
Node_B.append(B[j])
break
j += 1
i += 1
j = 0
I have a numpy array in this form:
array([['A', 2.2, 9.1],
['A', 7.1, 2.3],
['B', 4.1, 1.1]],dtype=object)
So I would like to query 'A' and then return all rows and columns with (matching) the string 'A'. Anything not matching the condition is ignored. So the output should be:
form = array([['A', 2.2, 9.1],
['A', 7.1, 2.3],dtype=object)
I tried using j = form[np.where(form == 'A')]
which gives array(['A', 'A'], dtype=object). This is not what I want.
Could someone please let me know how I can do this?
You can slice the array when using np.where() so that only this first column is used:
form = np.array([['A', 2.2, 9.1],
['A', 7.1, 2.3],
['B', 4.1, 1.1]],dtype=object)
j = form[np.where(form[:,0]=='A')]
print (j)
# [['A' 2.2 9.1]
# ['A' 7.1 2.3]]
You can avoid using where like so:
form = np.array([['A', 2.2, 9.1],
['A', 7.1, 2.3],
['B', 4.1, 1.1]])
print(form[form[:,0] == 'A'])
# [['A' 2.2 9.1]
# ['A' 7.1 2.3]]
Try creating a list comprehension then in it we iterate trough the length of test then check if 'A' is in the list witch is the element with the index of i:
import numpy as np
test = np.array([['A', 2.2, 9.1],
['A', 7.1, 2.3],
['B', 4.1, 1.1]],dtype=object)
print(test[[i for i in range(len(test)) if 'A' in test[i]]])
Output:
[['A' 2.2 9.1]
['A' 7.1 2.3]]
Quick and dirty way:
import numpy as np
form = np.array([row for row in form_original if row[0] == "A"])