Slice a list in python - python

I have a list in python like:
l = [1,2,4,5,7,8,2,1]
I want a code that will check if the number before in the list is bigger that the next one. And if it is i want the code to remove the the number. I want my code to return [1,2,4,5,7,8] and remove the last 2 and 1.
Pseudo code:
If l[i] > l[i+1]
remove l[i+1]
then check if l[i] is bigger than the next one after that. What use to be l[i+2]
Can someone help me?

Started with your list and appended based upon your criteria to a new one.
l = [1,2,4,5,7,8,2,1]
result = []
chk = 0
for num in l:
if chk > num:
pass
else:
chk = num
result.append(num)
print result
Apparently it is bad practice to delete entries from lists within a loop , so this is a workaround.

Iterating through array if there is array[i] > array[i+1] then remove array[i+1].
array = [1,2,4,5,7,8,2,1]
l = len(array)
first = 0
secound = 1
while secound != l:
if array[first] > array[secound]:
del array[secound]
l -= 1
else:
first += 1
secound += 1
print(array)

You can use itertools groupby to find areas of lists that fulfill a condition; in this case, each number is larger than the number proceeding:
from itertools import groupby
l = [1,2,4,5,7,8,2,1]
for k, g in groupby(enumerate(l[1:],1), key=lambda (i,e): e>l[i-1]):
if k:
grp=list(g)
print l[grp[0][0]-1:grp[-1][0]+1]
# [1, 2, 4, 5, 7, 8]
This will find any area in the list that meets that condition:
l = [1,2,4,5,7,8,2,5]
for k, g in groupby(enumerate(l[1:],1), key=lambda (i,e): e>l[i-1]):
if k:
grp=list(g)
print l[grp[0][0]-1:grp[-1][0]+1]
# prints [1, 2, 4, 5, 7, 8] and [2, 5]
So break after the first if you only want 1 group:
l = [10, 11, 12, 1, 2]
for k, g in groupby(enumerate(l[1:],1), key=lambda (i,e): e>l[i-1]):
if k:
grp=list(g)
print l[grp[0][0]-1:grp[-1][0]+1]
break
# [10, 11, 12]

you can do this even in one line:
l = l[0:1] + [el for index,el in enumerate(l[0:]) if el >l[index-1]]
#l[0:1] + is ugly but i couldnt figure out another way to get the
#first element since in python l[-1] = l[len(l)-1]

Related

Merge two sorted arrays using for loop is missing the last item

I m new to dealing with algorithms and my challenge was to merge two sorted lists into one using for loop not while loop. I got stuck at determining the end of the list:
list1=[1,2,4]
list2=[1,3,4,6]
def mergeTwoLists(list1: list, list2:list) -> list:
l = 0
r = 0
lRange = len(list1)-1
rRange = len(list2)-1
total_range = (len(list1)+len(list2))-1
merger = []
for i in range(total_range):
if list1[l]<=list2[r]:
merger.insert(i,list1[l])
if l<lRange:
l+=1
elif list1[l]>list2[r]:
merger.insert(i,list2[r])
if r<rRange:
r+=1
return(merger)
It returns [1,1,2,3,4,4] and missing the last value 6.
Following works for different kinds of lists. It gets items from the lists in an asynchronous manner and breaks out of loop when length of any one list is finished. Finally, it appends any excess items from the other list.
def mergeSortedLists(l1, l2):
outlist =[]; i=0; j=0;
while i<len(l1) and j<len(l2):
a = l1[i]; b = l2[j]
if a<b:
outlist.append(a); i+=1
else:
outlist.append(b); j+=1
outlist += l1[i:] + l2[j:]
print(outlist)
Try:
list1=[1,2,4]
list2=[1,3,4,6,7]
mergeSortedLists(list1, list2)
output:
[1, 1, 2, 3, 4, 4, 6, 7]
Or:
list1=[1,2,3]
list2=[4,5,6,8]
mergeSortedLists(list1, list2)
Output:
[1, 2, 3, 4, 5, 6, 8]
You're missing the last element because you subtract 1 when creating total_range.
You need to test which index is still within range inside the loop. You can only compare elements while both indexes are in range for their respective lists. Once you reach the end of one of the lists, just copy the rest of the other list to the result.
def mergeTwoLists(list1: list, list2:list) -> list:
l = 0
r = 0
lRange = len(list1)
rRange = len(list2)
total_range = lRange + rRange
merger = []
for i in range(total_range):
if l < lRange and r < rRange:
if list1[l]<=list2[r]:
merger.append(list1[l])
l+=1
elif list1[l]>list2[r]:
merger.append(list2[r])
r+=1
elif l < lRange:
merger.extend(list1[l:])
break
else:
merger.extend(list2[r:])
break
return(merger)
list1=[1,2,4]
list2=[1,3,4,6]
print(mergeTwoLists(list1, list2))

Finding all elements greater than current element in a list

If I have an array in Python in which all of the elements have different values, e.g. [1,4,6,2,10,3,5],
is there a way to find the total number of values in the list that are greater than the current index?
So for example, using the above list of length 7, the result I'd like to get is another list of length 7 which looks like [6,3,1,5,0,4,2]. I was having trouble trying to loop through the list (the code I tried to use is below)
for i in data:
count = np.sum(data > data[i])
N[i]=count
where data is the array containing all the pertaining values and N is an np.zeros list of the same length as data
You were very close. for i in data iterates through each element, not the indices as in Java/C.
Use range(len(data)) instead.
import numpy as np
data = np.array([1,4,6,2,10,3,5])
out = np.array([0]*7)
for i in range(len(data)):
count = np.sum(data > data[i])
out[i] = count
print(out) # [6 3 1 5 0 4 2]
Another way to write the loop is to use enumerate(), which returns an iterator of pairs of (indices, elements).
for i, x in enumerate(data):
count = np.sum(data > x)
out[i] = count
Here is my suggestion:
We sort the original list (l) and save it in a new list m. We create a new list (k) where we save the count of elements that are found on the right of the position of each element in m. See below:
l=[1,4,6,2,10,3,5]
m=sorted(l)
#[1, 2, 3, 4, 5, 6, 10]
k=[]
for i in l:
k.append(len(m)-m.index(i)-1)
>>> print(k)
[6, 3, 1, 5, 0, 4, 2]
Something like this?
list = [1,4,6,2,10,3,5]
list2 = []
v = len(list)
for x in list:
if x > v:
pass
else:
list2.append(x)
print(list2)
EDIT ¯\_(ツ)_/¯ (To see the total number of elements greater than the current element)
list = [1,4,6,2,10,3,5]
list2 = []
v = len(list)
total = 0
for x in list:
if x > v:
pass
else:
list2.append(x)
for y in list2:
total += 1
list2 = str(list2).replace('[', '')
list2 = list2.replace(']', '')
print("Now - " + list2 + ", in total of " + str(total) + " numbers ;)")
Output -
Now - 1, 4, 6, 2, 3, 5, in total of 6 numbers ;)
Alternatively, you can do it by using vectorize as follows:
>>> data = np.array( [1,4,6,2,10,3,5] )
>>> np.vectorize(lambda a, b : np.sum(a>b), excluded = [0] )(data, data)
array([6, 3, 1, 5, 0, 4, 2])

Add items in a list until their sum exceeds a threshold

From a list of values I want to create a new list of values until they add up a value.
I am new with Python but I believe it is best done with a while loop.
L = [1,2,3,4,5,6,7,8,9]
i = 0
s = 0
while i < len(L) and s + L[i] < 20:
s += L[i]
i += 1
numpy arrays make this simple
import numpy as np
arr = np.array(L)
arr[arr.cumsum() <= 20].tolist()
#[1, 2, 3, 4, 5]
Since you tagged Pandas:
pd.Series(L, index=np.cumsum(L)).loc[:20].values
Output:
array([1, 2, 3, 4, 5], dtype=int64)
You first create the empty list, and then append values with the same conditions you stated. Finally printing the list will return you the values that got added that match your criteria:
L = [1,2,3,4,5,6,7,8,9]
i = 0
s = 0
new_list = []
while i < len(L) and s + L[i] < 20:
new_list.append(L[i])
s += L[i]
i += 1
print(new_list)
Output:
[1, 2, 3, 4, 5]
You can easily write your own generator function:
L = [1,2,3,4,5,6,7,8,9]
def takeuntil(lst, max_value = 0):
"""Yields elements as long as the cummulative sum is smaller than max_value."""
total = 0
for item in lst:
total += item
if total <= max_value:
yield item
else:
raise StopIteration
raise StopIteration
new_lst = [item for item in takeuntil(L, 20)]
print(new_lst)
Which yields
[1, 2, 3, 4, 5]
If you would sum from start to end the (imo) more pythonic way would be
s = 0
for element in L:
if s + element < 20:
s += element
else:
break
If we’re talking pythonic, a for loop makes more sense (also using better variable names):
data = [1,2,3,4,5,6,7,8,9]
filtered = []
for num in data:
if num < 20:
filtered.append(num)
But a comprehension is also pythonic and shorter:
filtered = [num for num in data if num < 20]
Then to get the sum just use the sum function:
total = sum(filtered)
Or if you only need the sum:
total = sum(n for n in data if n < 20)

How to find the smallest missing numbers from a list without using inbuilt functions or modules

Here is my list:
List = [[1,2,4,5], [1,2,3,4,5,7], [1,4,5,6], [2,3,5], [1,2,3]]
From this how to find all the smallest missing numbers?
Edit:
The "smallest missing number" is the first integer (> 0) that is not in the list.
The expected output for the example input is 3, 6, 2, 1 and 4.
The input lists are always sorted.
An approach without any built-in functions:
Lists = [[1,2,4,5],[1,2,3,4,5,7],[1,4,5,6]]
for List in Lists:
i = 1
while i <= List[-1] + 1:
if i in List:
i += 1
else:
break
print i
Basically it processes each List separately (is that what you want?). It iterates a counter i starting at 1 (assuming you look for integers > 0) and stops, as soon as List doesn't contain i.
Output:
3
6
2
If the sublists are already sorted like you input, just compare the previous to the current element, if the prev +1 is not equal to the current ele add prev + 1 to the output list:
List = [[1, 2, 4, 5], [1, 2, 3, 4, 5, 7], [1, 4, 5, 6]]
out = []
for sub in List:
prev = sub[0]
for ele in sub[1:]:
if prev + 1 != ele:
out.append(prev +1)
break
prev = ele
print(out)
[3, 6, 2]
It will work for any sublists that are ordered not just lists starting with 1:
List = [[3, 4, 5,7], [10,13,14,15], [100,101,104,105]]
Output:
[6, 11, 102]
And without slicing:
out = []
for sub in List:
prev = sub[0]
i = 0
for ele in sub:
if i == 0:
i += 1
continue
if prev + 1 != ele:
out.append(prev +1)
break
prev = ele
print(out)
If you always want to find the first missing number starting at 1 and can have 0 or negative numbers, only check each ele and increase i if the ele is > 0:
out = []
for sub in Lists:
i = 1
for ele in sub:
if ele > 0:
if ele != i:
out.append(i)
break
i += 1
print(out)
That means at worst you do a single pass over each sublist as opposed to O(n^2) approach using in
Inspired by this answer:
List = [[1,2,4,5],[1,2,3,4,5,7],[1,4,5,6]]
print [sorted(set(range(1,max(l)+2)).difference(l))[0] for l in List]
Output:
[3, 6, 2]
Sure, this approach uses built-in functions. But you can start from here and break it down by replacing forbidden functions by your own implementations.

How to perform a pairwise swap of a list?

I want to write a small code in python that Swap Elements in a list this program will accept a list, and will return a list that exchanges the positions of each pair of adjacent elements: positions 0 and 1, positions 2 and 3, and so on. If the list has an odd number of elements, then the element in the last position stays “in place”.
Before: [1,2,3,4,5]
After: [2,1,4,3,5]
This looks unpythonic. What is the Python way to do it?
Here is a neat one, if you are always guaranteed to have even numbers:
nums = [1,2,3,4,5,6]
print([nums[i^1] for i in range(len(nums))])
>>[2, 1, 4, 3, 6, 5]
Explanation:
print (0^1) #1
print (1^1) #0
print (2^1) #3
print (3^1) #2
print (4^1) #5
print (5^1) #4
As a refresher, the XOR has the following effect:
A B | Output
---------------
0 0 0
0 1 1
1 0 1
1 1 0
And the official description: Each bit of the output is the same as the corresponding bit in x if that bit in y is 0, and it's the complement of the bit in x if that bit in y is 1.
Most pythonic way:
def swappairwise(a):
l = len(a)&~1
a[1:l:2],a[:l:2] = a[:l:2],a[1:l:2]
Building on the answer above from #Arpegius, here a, hopefully, somewhat more readable solution. Uses the same approach.
def swap_list_pairwise(lis):
"""Pairwise swap of all elements in a list.
If the number of elements is odd, the leftover element
stays at its place.
"""
length = len(lis)
# Stop at second last if length is odd, otherwise use full list.
end = length - 1 if length % 2 else length
lis[1:end:2], lis[:end:2] = lis[:end:2], lis[1:end:2]
If you want "pythonic", try "How do you split a list into evenly sized chunks in Python?", followed by a map() that reverses every chunk. May not be too performant, though.
(Oh, forgot the flattening of the list at the end)
Here is a way:
def pairwise_swap(iterable):
for i, value in enumerate(iterable):
if i % 2 == 0:
saved = value
else:
yield value
yield saved
>>> list(pairwise_swap(range(10)))
[1, 0, 3, 2, 5, 4, 7, 6, 9, 8]
Nice approach by #Alok above. This should fix the missing last
element if the number of elements is odd.
def pairwise_swap(iterable):
"""Pairwise swap of all elements in an iterable.
If the number of elements is odd, the leftover element
stays at its place.
"""
for i, value in enumerate(iterable):
if i % 2 == 0:
saved = value
else:
yield value
yield saved
# Don't forget the last element if `iterable` has an odd
# number of elements. Since counting starts a zero, we need
# to test if `i` is even.
if iterable and i % 2 == 0:
yield value
How about trying this one out?
>>> l = [1,2,3,4,5,6]
>>> pl = [l[i:i+2] for i in range(0,len(l),2)]
>>> pl
[[1, 2], [3, 4], [5, 6]]
>>> for i in pl:
... i[0],i[1] = i[1],i[0]
... print i
...
[2, 1]
[4, 3]
[6, 5]
>>> pl
[[2, 1], [4, 3], [6, 5]]
>>>
>>> zpl = [i for sublist in pl for i in sublist]
>>> zpl
[2, 1, 4, 3, 6, 5]
>>>
I tried to resolve in the easiest way out.
It will work for both even and odd elements. if list elements are even
first part will work if not else will do his task.
a = list(input("Put your list here: "))
len_a = len(a)
last_element = len_a-1
result = 0
if len_a % 2==0:
for i in range(0, len(a), 2):
a[i], a[i + 1] = a[i + 1], a[i]
print("its if",a)
else:
a_n = a.pop()
for i in range(0, len(a), 2):
a[i], a[i + 1] = a[i + 1], a[i]
a.insert(0,a_n)
# a.insert(last_element,a_n) if you want last element remain unmodified
print("its else:",a)
This is what worked for me. Hopefully, it can help others. I think about using boxes. The value in the first position needs a temporary place to be before it can be swapped, so I assign it to x and then make the swap. Incrementing by 2 will skip over the last element, so it's okay with odd-numbered lists as well.
a = [int(s) for s in input().split()]
i = 0
while i in range(0, len(a) - 1):
x = a[i]
a[i] = a[i + 1]
a[i + 1] = x
i += 2
print(a)
Found this to be much simpler solution and handels the list with odd elements
elements = list(map(int,input().split()))
swap = []
i = 0
while i < len(elements):
if i+1 < len(elements):
swap.append(elements[i+1])
swap.append(elements[i])
else:
swap.append(elements[-1])
i = i+2
print(swap)

Categories