Can I write an if/else condition in a list comprehension? I have not been able to use any of what I've found - python-3.x

I am trying to do an if/else with a list comprehension (I think). I tried to follow a normal if conditional format with the if/else at the end. I tried to add 'num for num in nums'. A few other things like the commented code at the bottom...but the best I can do is make res[] a list of 'None's.
I'm sure this will never be crucial and a normal if/else in a for loop works, it's just that I read Trey Hunner's visual take on List Comps and wondered about an else.
nums = [2,53,4,7,11,1]
print(nums)
res = []
for num in nums:
if num <= 7:
res.append("less")
else:
res.append("more")
print(res)
nums = [2,53,4,7,11,1]
print(nums)
res = []
res = [res.append("less") if num <= 7
else res.append("more")
for num in nums
]
print(res)
# [a if tC else b for i in items if fC]
# [item
for sublist in myList
for item in (sublist if type(sublist) is list else sublist['val'])
]

You can do it this way:
["less" if num <= 7 else "more" for num in nums]
Your second chunk of code is broken: you call res.append inside the list comprehension. Don't do that, you just need to produce individual values as I've done above.

Related

how to check if a given list of numbers are odd or even?

I want to check the numbers in a list are even or odd in order and if not tell me which one.
for example :
1,2,3,4,5 IS OK
but:
1,2,8,3,4,5 number 8 IS NOT OK
I tried to make the list into 2 different lists and then check if the are all odd or all even but I can't
figure out how to check both of them.
lst = [1,2,3,4,5,6,7,8,9,10]
m = lst[::2]
w = lst[1::2]
for i, j in(m,w):
if i % 2 == 0 and j % 2 == 0:
Try with
list(map(lambda el: 'odd' if el%2 else 'even', lst))

saving the result of the recursion iterations

This is a standart permutation function. Im tring to return the list of the lists of the permutations)
Could you help me with storaging the result of the recursion iterations? for example this code returns nonsense. It would be perfect if there was no global variable and rezulting list was inside the func
Thanks!
'''
z=[]
def func(N,M=-1,pref=None):
global z
if M == -1:
M = N
pref = pref or []
if M==0:
z.append(pref)
print(pref)
for i in range(N):
if i not in pref:
pref.append(i)
func(N,M-1,pref)
pref.pop()
func(3)
print(z)
'''
You are passing a list (pref variable in for loop) reference to your function and you are removing a single item from that and that's why you are ending with an empty list z.
Create a new list or copy the list before passing it to the function to avoid this situation.
z = []
def func(N, M=-1, pref=None):
global z
if M == -1:
M = N
pref = pref or []
if M == 0:
z.append(pref)
print(pref)
for i in range(N):
if i not in pref:
pref.append(i)
func(N, M - 1, pref[:])
pref.pop()
func(3)
print(z)
For better understand please read this one. List changes unexpectedly after assignment. How do I clone or copy it to prevent this?
If you want to have some kind of accumulator you must pass it to the recursion function, beware it could be a little nightmare.

list comprehension for empty list python 3?

I have an python 3 code as follow:
a = []
b = [[0] * len(a[0]) for _ in range(len(a))]
The above code works fine, but the follow code does not work:
a = []
m, n = len(a), len(a[0])
len(a[0]) apppears in both codes, why the list comprehension does not through IndexError: list index out of range.
Thanks,
range(len(a)) in this case is essentially range(0), which is an empty range:
>>> list(range(0))
[]
Because the collection being iterated over is empty, the comprehension never runs, so a[0] is never evaluated.
It's similar to how this loop prints nothing:
for _ in []:
print("SOME TEXT!")
[] is empty, so the for loop never iterates.
With m, n = len(a), len(a[0]) however, a[0] is run regardless of the length of a, so a[0] is evaluated, and you get an error.

iteration and matching items in lists

Am trying to check if elements of a list match elements of another. But there is a slight twist to the problem.
alist = ['949', '714']
blist = ['(714)824-1234', '(419)312-8732', '(949)555-1234', '(661)949-2867']
Am trying to match the elements of alist to the blist, but only the area code part(in blist). Here is my current code:
def match_area_codes(alist, blist):
clist =[]
for i in alist:
for j in blist:
if i in j:
clist.append(j)
return clist
The code works for the most part, except when there is a string matching the area code anywhere else in the list. It should only print:
['(714)824-1234', '(949)555-1234']
but it ends up printing
['(714)824-1234', '(949)555-1234', '(661)949-2867']
as there is a '949' in the last phone number. Is there a way to fix this?
You can use a regular expression to get the part within (...) and compare that part to alist.
import re
def match_area_codes(alist, blist):
p = re.compile(r"\((\d+)\)")
return [b for b in blist if p.search(b).group(1) in alist]
Example:
>>> alist = set(['949', '714'])
>>> blist = ['(714)824-1234', '(419)312-8732', '(949)555-1234', '(661)949-2867']
>>> match_area_codes(alist, blist)
['(714)824-1234', '(949)555-1234']
If you really really want to do it without regular expressions, you could, e.g., find the position of the ( and ) and thus get the slice from the string corresponding to the region code.
def match_area_codes(alist, blist):
find_code = lambda s: s[s.index("(") + 1 : s.index(")")]
return [b for b in blist if find_code(b) in alist]
However, I would strongly suggest to just take this as an opportunity for getting started with regular expressions. It's not all that hard, and definitely worth it!

k way merge sort divide and conquer

from math import ceil
def merge(all_lst):
sorted_lst = []
while all_lst:
min_value,index = all_lst[0][0],0
for lst in all_lst:
if lst[0]<min_value:
min_value = lst[0]
index = all_lst.index(lst)
sorted_lst.append(min_value)
all_lst[index].pop(0)
if not all_lst[index]:
all_lst.remove(all_lst[index])
return sorted_lst
def merge_sort(lst, k):
def split(lst):
split_lst = []
j = ceil(len(lst)/k) if len(lst)>=k else 1
for i in range(0,len(lst),j):
split_lst.append(lst[i:i+j])
return split_lst
lst=split(lst)
if len(lst[0])==1:
return lst
else:
for i in range(len(lst)):
lst[i]=merge(merge_sort(lst[i],k))
return merge(lst)
Above is my code for k-way merge sort. Basically what it does is split the list into k smaller list by calling the split function until each sublist in the list is a single element. Then the list containing sublists will be merged into one single list.
My code works fine when splitting is done twice. (eg.[3,6,8,5,2,1,4,7] -> [3,6,8],[5,2,1],[4,7] -> [3],[6],[8],[5],[2],[1],[4],[7]). But when the splitting is done more than twice, (eg,[3,6,8,5,2,1,4,7] -> [3,6,8,5],[2,1,4,7] -> [3,6],[8,5],[2,1],[4,7] -> [3],[6],[8],[5],[2],[1],[4],[7]), the code will fail. Can anyone help find me find out what goes wrong in my code? Thanks in advance.
I believe the problem you're having is that merge_sort sometimes returns a flattened list and other times returns a list of lists. You should probably return a flat list in all cases. There's some other cruft: You don't need split to be its own function, since you only call it the one time.
Here's a greatly simplified version of your code:
def merge_sort(lst, k):
if len(lst) == 1: # simpler base case
return lst
j = ceil(len(lst)/k) # no need to check for k < len(lst) (ceil handles it)
#split and recursively sort in one step
lst = [merge_sort(lst[i:i+j], k) for i in range(0, len(lst), j)]
return merge(lst) # always return a merged list (never a list of lists)

Resources