Compare elements of two list - python

I have been given two lists, say list1 and list2. I have to arrange the elements of the list1 in such a way that at particular index the element of list1 is greater than the element of list2. We have to find how many such elements of list1 are there.
For example:
list1=[20,30,50]
list2=[60,40,25]
Here only element index 2 is greater i.e. 50>25, but if we swap 50 and 30 in list1
So,
list1=[20,50,30]
list2=[60,40,25]
then 50 > 40 ( at index 1) and 30 > 25 (at index 2). So we got 2 elements 50 and 30 which are greater at their respective index.
Here is my approach
def swap(a,b):
a,b=b,a
return a,b
n=3
g=list(map(int,input().split()))
o=list(map(int,input().split()))
c=0
for i in range(n):
if o[i]>g[i]:
for j in range(i+1,n):
if g[j]>o[i]:
g[i],g[j]=swap(g[i],g[j])
c+=1
break
else:
c+=1
print(c)
But for
list1= [3,6,7,5,3,5,6,2,9,1]
list2= [2,7,0,9,3,6,0,6,2,6]
Its giving c=6 but expected output is c=7

You have to sort the two lists and then run through them to find "matches" where a value of list1 is greater than the next value of list2. This will pair up the values with the smallest possible difference and thus maximize the pairings.
For example:
list1=[20,30,50]
list2=[60,40,25]
iter1 = iter(sorted(list1)) # iterator to run through sorted list1
n1 = next(iter1,None) # n1 is current number in list1
count = 0 # count of paired elements (n1>n2)
for n2 in sorted(list2): # go through sorted list 2
while n1 is not None and n1 <= n2: # skip over ineligible items of list1
n1 = next(iter1,None)
if n1 is None: break # stop when list 1 is exhausted
count += 1 # count 1 pair and move on to next of list2
print(count) # 2

list1= [3,6,7,5,3,5,6,2,9,1]
list2= [2,7,0,9,3,6,0,6,2,6]
list1 = sorted(list1)
it = iter(enumerate(list1))
list2 = sorted(list2)
c = next(it)
good = []
for i, n in enumerate(list2 ):
try:
while c[1] < n:
c = next(it)
good.append([i, c[0]])
c = next(it)
except StopIteration:
break
for idx1, idx2 in good:
list1[idx1], list1[idx2] = list1[idx2], list1[idx1]
final_l1_l2 = sum(a > b for a, b in zip(list1, list2))# how many l1 are > l2
print(final_l1_l2)
output:
7
also, you can print list1 and list2 after the rearrange:
print(list1)
print(list2)
output:
[1, 2, 3, 3, 5, 6, 6, 7, 9, 5]
[0, 0, 2, 2, 3, 6, 6, 6, 7, 9]
the idea is to sort both lists and then to check what elements from list1 are greater than the elements from list2 if one element from list1 it is smaller then the current element from list2 just go to the next element from the list1 till there are no more elements in list1

Related

list index out of range in a merge and sort function

I tried writing a simple merge and sort function in python and got stuck after getting the following error-
List out of range.
I would appreciate if you could help me fix it and figure out how to avoid it. I have added the code below-
def merge(lst1, lst2):
# Gets two sorted lists and returns one merged and sorted list
merge_sorted = []
i = 0
j = 0
len1 = len(lst1) - 1
len2 = len(lst2) - 1
while i < len1 or j < len2:
if lst1[i] < lst2[j]:
merge_sorted.append(lst1[i])
i += 1
elif lst1[i] > lst2[j]:
merge_sorted.append(lst2[j])
j += 1
else:
merge_sorted.append(lst1[i])
merge_sorted.append(lst2[j])
i += 1
j += 1
return merge_sorted
lst1 = [2, 4, 5, 6, 8]
lst2 = [1, 3, 7, 9, 0]
merge(lst1, lst2)
What I got:
IndexError Traceback (most recent call last)
<ipython-input-13-572aad47097b> in <module>()
22 lst1 = [2, 4, 5, 6, 8]
23 lst2 = [1, 3, 7, 9, 0]
---> 24 merge(lst1, lst2)
<ipython-input-13-572aad47097b> in merge(lst1, lst2)
7 len2 = len(lst2) - 1
8 while i < len1 or j < len2:
----> 9 if lst1[i] < lst2[j]:
10 merge_sorted.append(lst1[i])
11 i += 1
IndexError: list index out of range
Your problem is the while condition:
while i < len1 or j < len2:
it should be and - if either of the conditoins are not true, you simple append the remainder of the non-empty list to your result and you are done.
Your current code still enters the while-body and checks if lst1[i] < lst2[j]: if one of the i / j is bigger then the list you get the error you have.
The full fixed code:
def merge(lst1, lst2):
# Gets two sorted lists and returns one merged and sorted list
merge_sorted = []
i = 0
j = 0
len1 = len(lst1) - 1
len2 = len(lst2) - 1
while i < len1 and j < len2: # use and
if lst1[i] < lst2[j]:
merge_sorted.append(lst1[i])
i += 1
elif lst1[i] > lst2[j]:
merge_sorted.append(lst2[j])
j += 1
else:
merge_sorted.append(lst1[i])
merge_sorted.append(lst2[j])
i += 1
j += 1
# add remainder lists - the slices evaluate to [] if behind the list lengths
merge_sorted.extend(lst1[i:]) # if i is aready out of the list this is []
merge_sorted.extend(lst2[j:]) # if j is aready out of the list this is []
return merge_sorted
lst1 = [2, 4, 5, 6, 8]
lst2 = [0, 1, 3, 7, 9] # fixed input, needs to be sorted, yours was not
print(merge(lst1, lst2))
Output:
[0, 1, 2, 3, 4, 5, 6, 8, 7, 9]
As suggested by other techies you can modify and run the program but you are simply increasing the time complexity of your program which you could have done in two lines.
Just extend the list1 elements like
list1.extend(list2)
once the elements are into the list1
print(set(sorted(list1)))
First of all, Your logic is wrong! You are picking the lower numbers and putting them into the list. but what about the biggest number of all? You will be stuck there! Because you will never pick the last one!
I changed the logic. Instead of counting up the iterators, I removed the picked ones! and when one list got empty the rest of the other one will join the final list.
and secondly, don't use the "merge" name for your function! It's occupied!
def merger(l1, l2):
merge_sorted = []
t1, t2 = sorted(l1), sorted(l2)
while len(t1) != 0 and len(t2) != 0:
if t1[0] <= t2[0]:
merge_sorted.append(t1[0])
t1 = t1[1:]
else:
merge_sorted.append(t2[0])
t2 = t2[1:]
return merge_sorted + (t1 if len(t1) != 0 else t2)
lst2 = [2, 4, 5, 6, 8]
lst1 = [1, 3, 7, 9, 0, 10]
print(merger(lst1, lst2))
Here are the values for i, j just before that if condition-
0 0
0 1
1 1
1 2
2 2
3 2
4 2
4 3
5 3
When any of the lists is traversed till the end, it throws index out of range error.
Solution-
Instead of using or condition, use and condition and append the remaining list elements at the end of the sorted list.

Iterating over two lists with certain condition

I have two lists, let's say
list1 = [1,2,3,4,5,6,7]
list2 = ["A", "B", "C"]
The condition is, that "A" in list2 relates to first 2 numbers in list1, "B" - to the next to numbers, "C" - to the all left numbers.
I try to create loop for these two lists so that as a result I could get the following:
1, A
2, A
3, B
4, B
5, C
6, C
7, C
I thought of using "for i in list1[:n]" construction where n - number of elements, but I cannot predefine n since the amount of elements in list1 that belong to the last element in list2 is unknown.
Here is my attempt:
s=0
n=2
for i in l1:
for t in l2[s:n]:
print (i,t)
s+=2
n+=2
You can use list comprehension to achieve that:
n = 2
# this is just the known length
res = [(y, x) for i, x in enumerate(list2) for y in list1[n*i:n*i+n]]
# just add the remaining items
res += [(x, list2[-1]) for x in list1[n*len(list2):]]
for x in res:
print(x)
list1 = [1,2, 3,4, 5,6,7]
list2 = ["A", "B", "C"]
items_to_iterate_on_list1_for_each_in_list2 = 2
index1 = 0
for item2 in list2:
# We iterate for each element in list 2
# on two elements of list 1
for offset in range(items_to_iterate_on_list1_for_each_in_list2):
print(f'{list1[index1 + offset]}, {item2}')
index1 += items_to_iterate_on_list1_for_each_in_list2
# If there are elements remaining in list1, we iterate over them with last element of list2
for i in range(index1, len(list1)):
print(f'{list1[i]}, {item2}')
Try the following code :
list1 = [1,2,3,4,5,6,7]
list2 = ["A", "B", "C"]
for j,i in enumerate(list1):
if j<2: print(list2[0],',',i)
elif j<4: print(list2[1],',',i)
else : print(list2[2],',',i)
You could make a list of index ranges that are to be used with slicing, and you can have None meaning the end of the list, so that the last slice is just however many items are left:
list1 = [1,2,3,4,5,6,7]
list2 = ["A", "B", "C"]
ranges = [(0, 2), (2, 4), (4, None)]
for r, letter in zip(ranges, list2):
for i in list1[slice(*r)]:
print(f'{i}, {letter}')
This gives
1, A
2, A
3, B
4, B
5, C
6, C
7, C
Solution similiar to your code:
list1 = [1,2, 3,4, 5,6,7]
list2 = ["A", "B", "C"]
items_to_iterate_on_list1_for_each_in_list2 = 2
s=0
n=2
for index2, item2 in enumerate(list2):
index1 = index2 * n
for t in list1[index1:index1 + n]:
print(f'{t}, {item2}')
# Adjust to last index1
index1 += n
# If there are elements remaining in list1, we iterate over them with last element of list2
for i in range(index1, len(list1)):
print(f'{list1[i]}, {item2}')
Another way of doing it is
list1 = [1,2,3,4,5,6,7]
list2 = ["A", "B", "C"]
for i in range(len(list1)):
index = min(i // 2, 2)
print(f"{list1[i]}, {list2[index]}")
As far as I can understand, you want to associate each item of list2 with every 2 items from list1. In case where the number of elements in list1 is more than 6, any element after 6th position (or index 5) will be associated with the last element of list2. Here is my approach:
list1 = [1,2,3,4,5,6,7,8,9]
list2 = ["A", "B", "C"]
for item in list1:
try:
print(item, list2[list1.index(item)//2])
except:
print(item, list2[-1])

Python3 - mergeSort implementation

I'm trying to implement mergeSort on my own, but the order of the returned list is still not correct. I must be missing something (especially by the merge step), could someone pls help me what it is?
Here is my code:
def merge(left_half, right_half):
"""
Merge 2 sorted lists.
:param left_half: sorted list C
:param right_half: sorted list D
:return: sorted list B
"""
i = 0
j = 0
B = []
for item in range(len(left_half) + len(right_half)):
while i < len(left_half) and j < len(right_half):
if left_half[i] <= right_half[j]:
B.insert(item, left_half[i])
i += 1
else:
B.insert(item, right_half[j])
j += 1
B += left_half[i:]
B += right_half[j:]
print("result: ", B)
return B
def mergeSort(A):
"""
Input: list A of n distinct integers.
Output: list with the same integers, sorted from smallest to largest.
:return: Output
"""
# base case
if len(A) < 2:
return A
# divide the list into two
mid = len(A) // 2
print(mid)
left = A[:mid] # recursively sort first half of A
right = A[mid:] # recursively sort second half of A
x = mergeSort(left)
y = mergeSort(right)
return merge(x, y)
print(mergeSort([1, 3, 2, 4, 6, 5]))
Before the last merge I receive the two lists [1, 2, 3] and [4, 5, 6] correctly, but my final result is [3, 2, 1, 4, 5, 6].
In the first iteration of your for-loop, you entirely traverse one of the lists, but always insert at index 0.
You do not want to insert an element, you always want to append it. This then makes the for-loop unecessary.
Here is a fixed version of your code:
def merge(left_half, right_half):
"""
Merge 2 sorted arrays.
:param left_half: sorted array C
:param right_half: sorted array D
:return: sorted array B
"""
i = 0
j = 0
B = []
while i < len(left_half) and j < len(right_half):
if left_half[i] <= right_half[j]:
B.append(left_half[i])
i += 1
else:
B.append(right_half[j])
j += 1
B += left_half[i:]
B += right_half[j:]
print("result: ", B)
return B
merge([1, 2, 3], [4, 5, 6])
# result: [1, 2, 3, 4, 5, 6]

creating sum of odd indexes python

I'm trying to create a function equal to the sum of every other digit in a list. For example, if the list is [0,1,2,3,4,5], the function should equal 5+3+1. How could I do this? My knowledge of Python does not extend much farther than while and for loops. Thanks.
Here is a simple one-liner:
In [37]: L
Out[37]: [0, 1, 2, 3, 4, 5]
In [38]: sum(L[1::2])
Out[38]: 9
In the above code, L[1::2] says "get ever second element in L, starting at index 1"
Here is a way to do all the heavy lifting yourself:
L = [0, 1, 2, 3, 4, 5]
total = 0
for i in range(len(L)):
if i%2: # if this is an odd index
total += L[i]
Here's another way, using enumerate:
L = [0, 1, 2, 3, 4, 5]
total = 0
for i,num in enumerate(L):
if i%2:
total += num
>>> arr = [0,1,2,3,4,5]
>>> sum([x for idx, x in enumerate(arr) if idx%2 != 0])
9
This is just a list comprehension that only includes elements in arr that have an odd index.
To illustrate in a traditional for loop:
>>> my_sum = 0
>>> for idx, x in enumerate(arr):
... if idx % 2 != 0:
... my_sum += x
... print("%d was odd, so %d was added. Current sum is %d" % (idx, x, my_sum))
... else:
... print("%d was even, so %d was not added. Current sum is %d" % (idx, x, my_sum))
...
0 was even, so 0 was not added. Current sum is 0
1 was odd, so 1 was added. Current sum is 1
2 was even, so 2 was not added. Current sum is 1
3 was odd, so 3 was added. Current sum is 4
4 was even, so 4 was not added. Current sum is 4
5 was odd, so 5 was added. Current sum is 9
let's take this list as an example:
l = [1,2,3,4,5]
for even indexes sum:
even_index_eles = l[1::2] # [2, 4]
sum(even_index_eles) # 6
for odd indexes sum:
odd_index_eles = l[::2] # [1, 3, 5]
sum(odd_index_eles) # 9
it's worked with odd or even length of list

Complex list and len computation

The following code has a output of [1, 3, 6, 10]. I understand how to get 1 and 3 but not 6 and 10.
In 1st loop, the first list item 1 is equal to[my_list[0]], 3 equals to [out_list[len(out_list)-1] + my_list[i]]
In 2nd loop, out_list = 4 + [1 + 3] = 8which is not 6...
def mystery(my_list):
out_list = [my_list[0]]
for i in range(1, len(my_list)):
out_list += [out_list[len(out_list)-1] + my_list[i]]
print(out_list)
mystery([1, 2, 3, 4]) #output[1, 3, 6, 10]
I'm very close to understand it, just need a bit more explanation. Am I right? 1st loop, out_list = 1, [out_list[len(out_list)-1] = 1, my_list[i]] = 2, therefore, [1, 3]. 2nd loop, out_list stays the same, then I'm stuck here...
output = mystery([1, 2, 3, 4]) # [1, 3, 6, 10]
output == [1, 1+2, 1+2+3, 1+2+3+4]
my_list initially is : [1, 2, 3, 4]
out_list initially is : [1]
out_list in 1 iteration outlist on each iter : [1]
here i is : 1
len(out_list) : 1 my_list[i]: 2
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[0] gives 1 add this to 2
out_list in 2 iteration outlist on each iter : [1, 3]
here i is : 2
len(out_list) : 2 my_list[i]: 3
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[1] gives 3 add this to 3
out_list in 3 iteration outlist on each iter : [1, 3, 6]
here i is : 3
len(out_list) : 3 my_list[i]: 4
add next element using this statement : out_list += [out_list[len(out_list)-1] + my_list[i]]
check here : out_list[2] gives 6 add this to 4
Finally output is : [1, 3, 6, 10]
out_list += [out_list[len(out_list)-1] + my_list[i]] this statement it appends previous element into out_list i.e why out_list += is used instead out_list = so only in 3rd and 4th iteration the result is 6 and 10
out_list[len(out_list)-1] is simply the last item in out_list, same as out_list[-1].
Adding items to the list is done obscurely. Doing lst += [smtn] is the same as doing lst.append(smtn)
Would this make the function more readable to you?
def mystery(my_list):
out_list = [my_list[0]]
for i in range(1, len(my_list)):
out_list.append(out_list[-1] + my_list[i])
print(out_list)
This code returns a list whose i's item is the sum of the first i items of the input. In the i iteration you take the sum of i-1 items (which is stored in i-1), and add the i-th item from the list. 3=1+2, 6=(1+2)+3, 10=(1+2+3)+4. Had the next item in my_list be 5, the next item in out_list would be 10+5 = 15.
Edit:
To clarify more, let's do it by stages.
my_list = [1,2,3,4] and we enter the method
upon entry, we have out_list = [my_list[0]]. so now out_list = [1].
Now we go into the loop:
First iteration, i=1. out_list[len(out_list)-1] + my_list[i] = out_list[0] + my_list[1] = 1 + 2 = 3. out_list = [1,3]
Second iteration, i=2. out_list[len(out_list)-1] + my_list[i] = out_list[1] + my_list[2] = 3 + 3 = 6. out_list = [1,3,6]
Third iteration, i=3. out_list[len(out_list)-1] + my_list[i] = out_list[2] + my_list[3] = 6 + 4 = 10. out_list = [1,3,6,10]
A pythonic way to do this really easily:
def summer_foo(my_list):
return [sum(my_list[:i+1]) for i in range(len(my_list))]
Brief explanation
Loop from 0 to the len of the list - len(my_list)
Sum all the elements which goes from 0 to i
Put this element in the list (this is done with the comprehension)
if iis equal to 0 you will get the first element.
if iis equal to 1 you will get the sum of the first and the second element (i belongs to [0,2))
And so on...

Categories