Assign matched item in list to a variable - python-3.x

The motive is to check if any of items in a list are contained in another list, and in case there is a match, assign it to a variable in a 'pythonic' fashion
if any('a','b','c') in ['b','x','y','z']:
#now i want to assign the matched 'b' to a variable concisely.
#In case of multiple matches , any match/ first match may be assigned
I want to avoid this :
lst = ['b','x','y','z']
if 'a' in lst:
var = 'a'
elif 'b' in lst"
var = 'b'
# and so on

You can use a function that returns either the first matched element or None in case no matched elements are found:
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
def find(li_1, li_2):
for e in li_1:
if e in li_2:
return e
print(find(li_1, li_2))
# b
print(find(['a'], ['b']))
# None
Note that this is an O(n^2) solution. If the items are hashable you can get an O(1) solution using sets intersection (and as a bonus you will get all matched elements):
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
s1 = set(li_1)
s2 = set(li_2)
print(s1.intersection(s2)) # or print(s1 & s2)
# {'b'}

Related

Check list for part of value and return whole value

I have a master list of ID numbers and another list of partial ID numbers. I need to check if the partial ID number is in the master list. If so, I need to return the whole ID number into a new list. What I have:
master_list = ['20000-K-A', '20000-K-B', '20000-K-C', '30000-R-X', '30000-R-V', '30000-R-F']
partial_list = [20000, 40000, 500000]
new_list =[]
for x in partial_list:
if x in master_list:
new_list.append(x)
print(new_list)
Now this only works if the partial ID number is EXACTLY what is in the master list. How do I return the value from the master list so that I can add it to the new list?
One option is to create a lookup dictionary first from master_list (note that the master_list is a list of strings while partial_list is a list of integers, so we need to cast the prefix to int):
d = {}
for item in master_list:
k, _ = item.split('-', maxsplit=1)
d.setdefault(int(k), []).append(item)
which looks like:
{20000: ['20000-K-A', '20000-K-B', '20000-K-C'],
30000: ['30000-R-X', '30000-R-V', '30000-R-F']}
Then iterate over partial_list to get the partially matching Ids:
new_list =[]
for x in partial_list:
new_list.extend(d.get(x, []))
Output:
['20000-K-A', '20000-K-B', '20000-K-C']

List Comprehension with "if" is not returning the same output as when I make a For Loop when counting the number of unique letters in a word

Can someone explain to me why there is a difference in output when using nested loops vs nested list comprehension?
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def unique_english_letters (word) :
unique = []
for i in word:
if i not in unique:
unique.append(i)
return len(unique)
print(unique_english_letters("mississippi"))
# outputs 4 (my expected output)
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def unique_english_letters (word) :
unique = []
unique = [i for i in word if i not in unique]
return len(unique)
print(unique_english_letters("mississippi"))
#outputs 11 (length of mississippi"
^ Output
In the second example, this:
unique = []
unique = [i for i in word if i not in unique]
is equivalent to:
unique = [i for i in word if i not in []]
unique is an empty list while the list comprehension is evaluated, and then unique is re-assigned the results.
To do what you want in simple terms, use a set which can only contain unique values, and use set intersection(& operator) to generate the set of letters contained in word:
letters = set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
def unique_english_letters(word):
return len(letters & set(word))
print(unique_english_letters("mississippi"))
# output: 4

how to add characters from array into one string python

I'm trying to change characters from x into upper or lower character depending whether they are in r or c. And the problem is that i can't get all the changed characters into one string.
import unittest
def fun_exercise_6(x):
y = []
r = 'abcdefghijkl'
c = 'mnopqrstuvwxz'
for i in range(len(x)):
if(x[i] in r):
y += x[i].lower()
elif(x[i] in c):
y += x[i].upper()
return y
class TestAssignment1(unittest.TestCase):
def test1_exercise_6(self):
self.assertTrue(fun_exercise_6("osso") == "OSSO")
def test2_exercise_6(self):
self.assertTrue(fun_exercise_6("goat") == "gOaT")
def test3_exercise_6(self):
self.assertTrue(fun_exercise_6("bag") == "bag")
def test4_exercise_6(self):
self.assertTrue(fun_exercise_6("boat") == "bOaT" )
if __name__ == '__main__':
unittest.main()
Using a list as you are using is probably the best approach while you are figuring out whether or not each character should be uppered or lowered. You can join your list using str's join method. In your case, you could have your return statement look like this:
return ''.join(y)
What this would do is join a collection of strings (your individual characters into one new string using the string you join on ('').
For example, ''.join(['a', 'b', 'c']) will turn into 'abc'
This is a much better solution than making y a string as strings are immutable data types. If you make y a string when you are constructing it, you would have to redefine and reallocate the ENTIRE string each time you appended a character. Using a list, as you are doing, and joining it at the end would allow you to accumulate the characters and then join them all at once, which is comparatively very efficient.
If you define y as an empty string y = "" instead of an empty list you will get y as one string. Since when you declare y = [] and add an item to the list, you add a string to a list of string not a character to a string.
You can't compare a list and a string.
"abc" == ["a", "b", "c'] # False
The initial value of y in the fun_exercise_6 function must be ""

Is there a way to test if two separate values, in two separate arrays, and check if they are equal or not?

Im trying to see if a value in one array is equal to that in another array, the values are integer values.
Ive tried turning them into string and integers from the array but get the error that they cannot be converted implicitly.
winningnumber = []
usernumber = []
print(winningnumber)
print(usernumber)
if(winningnumber == usernumber):
print("Exact number")
I would then get an output like so
[1]
['1']
In order to do this, what you want to do is access the first item of each array, and compare that value.
There are a lot of ways to do this, but here is a little driver program to show you one way.
# Defining a function to see if they match
def is_winning(arr1, arr2):
# Grabbing the first element in each array
# denoted by the [0], for the "0th" element
arr1_first_ele = arr1[0]
arr2_first_ele = arr2[0]
# If the first element in the first array matches the first element in the second
if arr1_first_ele == arr2_first_ele:
# Print out they match
print("They match")
# Otherwise
else:
# Print out that they dont
print("They don't match")
def main():
# Example arrays
test_array_one = [1,3,4]
test_array_two = [5,4,3]
# This should print out "They don't match"
is_winning(test_array_one, test_array_two)
# Example arrays
test_array_three = [6,7,8]
test_array_four = [6,5,4]
# This should print out "They match"
is_winning(test_array_three, test_array_four)
main()
This evaluates to:
They don't match
They match

uisng a for loop to print a backwards list?

Below is my code I have printing this in ascending order I now need to print it in descending order but don't know how? I have tried the below code however it is not printing my desired results i.e Jill,8,1,0 first and soon
sorted_list = ["jack",4,3,1,"jill",8,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(len(sorted_list),2,-3,-1):
des_list.append(sorted_list[i-2])
des_list.append(sorted_list[i - 1])
des_list.append(sorted_list[i])
des_list.append(sorted_list[i+1])
print(des_list)
OP is incredibly vague and I can't determine any way in which the list provided is 'sorted' while a reversal of the list would print out 'jill' first. At any rate, I've assumed:
The strings are supposed to be names
The ints that follow are attributes of the aforementioned names
With that, I created a dict that holds the names and attributes. This would be sorting by alphabetical name with the attributes in their original order.
sorted_list = ["jack",4,3,1,"jill",8,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
nameDict = {}
tmp = None
for _ in sorted_list:
if isinstance(_, str):
tmp = _
nameDict[tmp] = []
else:
if tmp: nameDict[tmp].append(_)
final = []
for name in list(reversed(sorted(nameDict))):
final += [name] + nameDict[name]
print final
While writing this, OP seems to have responded to my comment and apparently would like the attributes themselves in descending order.
sorted_list = ["jack",4,3,1,"jill",8,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
nameDict = {} # empty dictionary {key1 : value1, key2 : value2 } etc...
tmp = None # temporary variable used to keep track of the name
for _ in sorted_list:
if isinstance(_, str): # if the name is a string...
tmp = _ # ... set the temporary variable to the name
nameDict[tmp] = [] # create an entry in the dictionary where the value is an empty list. Example: { "jill" : [] }
else:
if tmp: nameDict[tmp].append(_) # as long as tmp is not None, append the value to it. For example, after we hit "jill", it will append 8 then 1 then 0.
final = [] # empty list to print out
for name in nameDict: # loop through the keys in nameDict
final += [name] + sorted(nameDict[name], reverse=True) # append the name to the final list as well as the sorted (descending) list in the dictionary
print final
If you need the names in their correct order, that might be a bit different because dicts are unsorted.

Resources