How to remove tuple from zip? - python-3.x

so i have a bunch of numbers i've tupled but am having difficulty remove an item from the zipped list.
so far i've tried .remove on the list but that gave me an error.
is there an easy way of doing this?
this is my current code:
Example data:
QueenRowColumn: 3,3
TheComparisonQueen: 7,3
def CheckQueenPathDown(self, QueenRowColumn, TheComparisonQueen):
row = []
column = []
CurrentLocation = QueenRowColumn
#MoveLocation = TheComparisonQueen
a = QueenRowColumn[0]
b = QueenRowColumn[1]
for i in range (-7,0):
row.append(CurrentLocation[1] - i)
column.append(a)
Down = zip(row,column)
#Down.remove(TheComparisonQueen)
return Down
if i, for example were to remove "TheComparisonQueen" from the list of tuples, how would i do it?

If you just looking to drop TheComparisonQueen from iterator of tuples you can return values that are not equal to TheComparisonQueen using a list comprehension or a generator expression.
# List Comprehension
Down = [(i,j) for i,j in zip(row,column) if (i,j) != TheComparisonQueen]
# Generator Expression
Down = ((i,j) for i,j in zip(row,column) if (i,j) != TheComparisonQueen)

Related

Find the index of a tuple when iterating across the first element of the tuple

How can you identify the index of a tuple when looping through a list of tuples[0]?
List = [('SPAM', 1.0),('EGGS', 4.2),('SPAM', 4.4),('BACON', 9.0),('COFFEE', 2.3)]
for i,j in List:
if i == 'SPAM':
list.remove(???)
print(list)
I've tried to employ the Enumerate() function, but that didn't seem to give me the correct output either.
List.pop()
Doesn't pop the correct index all the time.
Can anyone help, please?
Enumeration does work:
l = [('SPAM', 1.0),('EGGS', 4.2),('SPAM', 4.4),('BACON', 9.0),('COFFEE', 2.3)]
for idx, (i,j) in enumerate(l):
if i == 'SPAM':
print("FOUND SPAN at index %d" % idx)
However, you shouldn't mutate the list while iterating over it, rather take a filtering approach like so:
l_new = [(i, j) for i, j in l if i != 'SPAM']
You can use del to delete the element at the given index:
List = [('SPAM', 1.0),('EGGS', 4.2),('SPAM', 4.4),('BACON', 9.0),('COFFEE', 2.3)]
for (i, (e1, e2)) in enumerate(List):
if e1 == 'SPAM':
del List[i]
print(List) # prints [('EGGS', 4.2), ('BACON', 9.0), ('COFFEE', 2.3)]

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.

Python losing track of index location in for loop when my list has duplicate values

I'm trying to iterate over pairs of integers in a list. I'd like to return pairs where the sum equals some variable value.
This seems to be working just fine when the list of integers doesn't have repeat numbers. However, once I add repeat numbers to the list the loop seems to be getting confused about where it is. I'm guessing this based on my statements:
print(list.index(item))
print(list.index(item2))
Here is my code:
working_list = [1,2,3,4,5]
broken_list = [1,3,3,4,5]
def find_pairs(list, k):
pairs_list = []
for item in list:
for item2 in list:
print(list.index(item))
print(list.index(item2))
if list.index(item) < list.index(item2):
sum = item + item2;
if sum == k:
pair = (item, item2)
pairs_list.append(pair)
return pairs_list
### First parameter is the name is the list to check.
### Second parameter is the integer you're looking for each pair to sum to.
find_pairs(broken_list, 6)
working_list is fine. When I run broken_list looking for pairs which sum to 6, I'm getting back (1,5) but I should also get back (3,3) and I'm not.
You are trying to use list.index(item) < list.index(item2) to ensure that you do not double count the pairs. However, broken_list.index(3) returns 1 for both the first and second 3 in the list. I.e. the return value is not the actual index you want (unless the list only contains unique elements, like working_list). To get the actual index, use enumerate. The simplest implementation would be
def find_pairs(list, k):
pairs_list = []
for i, item in enumerate(list):
for j, item2 in enumerate(list):
if i < j:
sum = item + item2
if sum == k:
pair = (item, item2)
pairs_list.append(pair)
return pairs_list
For small lists this is fine, but we could be more efficient by only looping over the elements we want using slicing, hence eliminating the if statement:
def find_pairs(list, k):
pairs_list = []
for i, item in enumerate(list):
for item2 in list[i+1:]:
sum = item + item2
if sum == k:
pair = (item, item2)
pairs_list.append(pair)
return pairs_list
Note on variable names
Finally, I have to comment on your choice of variable names: list and sum are already defined by Python, and so it's bad style to use these as variable names. Furthermore, 'items' are commonly used to refer to a key-value pair of objects, and so I would refrain from using this name for a single value as well (I guess something like 'element' is more suitable).

How to use re.compile within a for loop to extract substring indices

I have a list of data from which I need to extract the indices of some strings within that list:
str=['cat','monkey']
list=['a cat','a dog','a cow','a lot of monkeys']
I've been using re.compile to match (even partial match) individual elements of the str list to the list:
regex=re.compile(".*(monkey).*")
b=[m.group(0) for l in list for m in [regex.search(l)] if m]
>>> list.index(b[0])
3
However, when I try to iterate over the str list to find the indices of those elements, I obtain empty lists:
>>> for i in str:
... regex=re.compile(".*(i).*")
... b=[m.group(0) for l in list for m in [regex.search(l)] if m]
... print(b)
...
[]
[]
I imagine that the problem is with regex=re.compile(".*(i).*"), but I don't know how to pass the ith element as a string.
Any suggestion is very welcome, thanks!!
It looks like you need to use string formatting.
for i in str:
match_pattern = ".*({}).*".format(i)
regex = re.compile(match_pattern)
b = [m.group(0) for l in list for m in [regex.search(l)] if m]
print(b)

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