Getting the value of List and sum in python - python

I newbie in python and I have a trouble how can I make my loop with that shape below and getting the total number of each line, I tried the code below but it seems it doesn't right
I should use list in loop like the declaration below, I appreciate who can help me.
data = [1, 2, 3, 4, 5]
Expected output:
[1, 2, 3, 4, 5, 15]
[2, 3, 4, 5, 14]
[3, 4, 5, 12]
[4, 5, 9]
[5, 5]
This is what I tried but it doesn't use list ,I think it's wrong
data = 5
for i in range(data):
for j in range(i+1):
print("[",j+1, end=" "+" ]")
print("[ ]")

Usually in these kind of exercises you shouldn't build the string yourself(talking about brackets). Those brackets are part of the representation of the lists in Python. So build your list object and the final result is gonna be printed as you expected. So don't attempt to put individual numbers, spaces, brackets together yourself.
You can use:
data = [1, 2, 3, 4, 5]
for i in range(len(data)):
slice_ = data[i:]
print(slice_ + [sum(slice_)])
Explanation:
Basically in every iteration, you create a slice of the list by specifying the start point to the end. Start point comes from the range(len(data)) range object.
first iteration : From index 0 to end.
second iteration: From index 1 to end.
...
Then you concatenate the slice with the sum of the slice. But you have to put the sum inside a list because a list can't be concatenated with an int. Of course other option is to .append() it before printing:
for i in range(len(data)):
slice_ = data[i:]
slice_.append(sum(slice_))
print(slice_)

Related

Get last and first n elements of a list

Need an answer where numbers to leave from the start and end can easily be adjusted.
Thanks.
This is my code:
ls = [1,2,3,4,5,6]
# desired output: [1,2,5,6]
#Tried the following:
ls[-2:2:1]
ls[2:4:-1]
# Both return empty list
If you don't mind modifying the original list in-place you can also delete the slice in the middle:
del ls[2:4]
ls would then become:
[1, 2, 5, 6]
Demo: https://replit.com/#blhsing/StylishFuzzyCopyrightinfringement
Code:-
# [ 0, 1, 2, 3, 4, 5] for positive indices
lis=[ 1, 2, 3, 4, 5, 6]
# [-6,-5,-4,-3,-2,-1] for negative indices
# desired output: [1,2,5,6]
#Some options are
print(lis[:2]+lis[4:])
print(lis[:2]+lis[-2:])
print(lis[-6:-4]+lis[-2:])
print(lis[-6:-4]+lis[4:])
Output:-
[1, 2, 5, 6]
[1, 2, 5, 6]
[1, 2, 5, 6]
[1, 2, 5, 6]
yes you can do slicing like ls[:2] + ls[-2:] to get the desired output
I read the documentation and tried some codes to see why your code fails.
clearly as shown in the documentation there is no problem with the step of slicing being a negative number. I think the problem is that you can not reach the end of the list (or the beginning if your step is negative) and start from the other side.
And for code to work as you want, you can use ls[:2] + ls[-2:] as suggested in the comments
You can parameterize the code to include how many elements you want from the start and end.
For e.g -
ls = [1,2,3,4,5,6]
# desired output: [1,2,5,6]
start = 2 #no of elements needed from start
end = 1 #no of elements needed from end
ls[:start] + ls[-end:] #gives you desired output
Try ls[2:-2] instead of ls[-2:2]

How to remove some elements from a list and append them at the beginning of the list in Python

Suppose that I have a list that has [0, 1, 2, 3 , 4, 5, 6] in it. I want to remove those elements that are greater than or equal to 3 and add those removed elements to the beginning of the list. So I wrote the code below:
list = [0, 1, 2, 3, 4, 5, 6]
new_list =[]
for number in list:
if number >= 3:
dropped_number = list.pop()
new_list.append(dropped_number)
new_list.sort()
new_list += list
print(new_list)
However, when I ran the code, the result was displayed as [5, 6, 0, 1, 2, 3 , 4]. Could anyone please explain to me at which step I did wrong here?
There are two issues with your code.
the number you obtain with list.pop() is not the one you just checked with your condition (it is merely the last one in the list)
When you reach 3, list.pop() removes 6,
When you reach 4, list.pop() removes 5,
You never reach 5 because you're at the end of what remains of the list at that point.
removing items from a list within a for-loop on the same list will cause the for-loop to skip items or complain that the list changed during iterations. So, even if you were to pop the appropriate number, your loop would miss items.
You also don't need to sort new_list every time you add to it, you can do it once at the end, but that just optimization.
Instead of a for-loop, you could use the sort method with a key parameter that returns a boolean indicating True for elements that do not meet your conditions (i.e that will be shifted to the right). Because Python's sort is stable, this will only place elements in two groups without otherwise changing their relative order.
L = [0, 2, 4, 6, 1, 3, 5]
L.sort(key=lambda x: not x>=3)
print(L) # [4, 6, 3, 5, 0, 2, 1]
If you need a more procedural solution, you can separate the values in two lists that you stick together at the end:
L = [0, 2, 4, 6, 1, 3, 5]
left,right = [], []
for x in L:
if x >= 3: left.append(x)
else: right.append(x)
L = left + right
# [4, 6, 3, 5, 0, 2, 1]
Modifying a list while iterating over it is usually problematic. What if instead you thought of the problem as building a new list out of two subsets of the original list?
>>> old_list = list(range(7))
>>> [i for i in old_list if i >= 3] + [i for i in old_list if i < 3]
[3, 4, 5, 6, 0, 1, 2]
The reason your program doesn't work is because you are modifying the list whilst searching through it. Instead, you can start by adding the elements >= 3 to a new list and then separately appending the elements < 3 to the list. Also, considering you are created a second 'new_list', there is no need to remove the elements from the first list.
Your new code:
list = [0, 1, 2, 3, 4, 5, 6]
new_list = []
# Append numbers greater than 3 to the new list
for number in list:
if number >= 3:
new_list.append(number)
# Append the numbers less than 3 to the new list
new_list += list[0:list.index(new_list[0])]
print(new_list)
Just to note, this method takes a section of the original list from position 0, to the position (.index) of the first item in the new list, which automatically generates the < 3 condition as the first item in the new list corresponds to the items before the >= 3 condition is met.
list[0:list.index(new_list[0])]

How to reorder a python list backwards starting with the 0th element?

I'm trying to go through a list in reverse order, starting with the -0 indexed item (which is also the 0th item), rather than the -1 indexed item, so that I'll now have the new list to use. I've come up with two ways to do this, but neither seems both concise and clear.
a_list = [1, 2, 3, 4, 5]
print(a_list[:1] + a_list[:0:-1]) # take two slices of the list and add them
# [1, 5, 4, 3, 2]
list_range = range(-len(a_list)+1,1)[::-1] # create an appropriate new index range mapping
print([a_list[i] for i in list_range]) # list comprehension on the new range mapping
# [1, 5, 4, 3, 2]
Is there a way in python 3 to use slicing or another method to achieve this more simply?
If you are up for a programming golf:
>>> a_list = [1, 2, 3, 4, 5]
>>> [a_list[-i] for i in range(len(a_list))]
[1, 5, 4, 3, 2]
I think your first suggestion is the cleanest way of doing this. If you're really optimizing for character count, you can remove two characters from the first slice:
print(a_list[:1] + a_list[:0:-1])
Shift everything left by one and reverse.
my_list.append(my_list.pop(0))
print my_list[::-1]

Python - iterating over lists

I want my code's 2nd function to modify the new list made by my 1st function.
If I am understanding things correctly giving a list as an argument will give the original list (my_list in this case).
so the code removes 1 & 5 and then adds 6, but not 7?
my_list = [1, 2, 3, 4, 5]
def add_item_to_list(ordered_list):
# Appends new item to end of list which is the (last item + 1)
ordered_list.append(my_list[-1] + 1)
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for items_to_remove in ordered_list:
ordered_list.remove(items_to_remove)
if __name__ == '__main__':
print(my_list)
add_item_to_list(my_list)
add_item_to_list(my_list)
add_item_to_list(my_list)
print(my_list)
remove_items_from_list(my_list, [1,5,6])
print(my_list)
output of
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 4, 6, 8]
instead of wanted
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 7, 8]
Thank you and sorry for the elementary question
In your remove_items_from_list function you are iterating through the wrong list. You should iterate through every item in the items_to_remove list like this:
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for item in items_to_remove:
ordered_list.remove(item)
This will now iterate through each item in the remove list and remove it from you ordered_list.
There is a bug in the remove_items_from_list function. For it to achieve what you want it should go:
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for item in items_to_remove:
ordered_list.remove(item)
As a side note, your code has incorrect number of blank lines before function definitions. Should be two blank lines before the function, and not more than one blank line inside functions. It seems not to have affected the code for now, but makes it harder to read, and could cause problems in future.
In the second function you want to iterate over items_to_remove (and not your original list) and then remove every item.
Use:
def remove_items_from_list(ordered_list, items_to_remove):
for item_to_remove in items_to_remove:
ordered_list.remove(item_to_remove)
And don't change the a list when you are iterating over it,which may cause bug.

Mysterious interaction between Python's slice bounds and "stride"

I understand that given an iterable such as
>>> it = [1, 2, 3, 4, 5, 6, 7, 8, 9]
I can turn it into a list and slice off the ends at arbitrary points with, for example
>>> it[1:-2]
[2, 3, 4, 5, 6, 7]
or reverse it with
>>> it[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]
or combine the two with
>>> it[1:-2][::-1]
[7, 6, 5, 4, 3, 2]
However, trying to accomplish this in a single operation produces in some results that puzzle me:
>>> it[1:-2:-1]
[]
>>>> it[-1:2:-1]
[9, 8, 7, 6, 5, 4]
>>>> it[-2:1:-1]
[8, 7, 6, 5, 4, 3]
Only after much trial and error, do I get what I'm looking for:
>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]
This makes my head hurt (and can't help readers of my code):
>>> it[-3:0:-1] == it[1:-2][::-1]
True
How can I make sense of this? Should I even be pondering such things?
FWYW, my code does a lot of truncating, reversing, and listifying of iterables, and I was looking for something that was faster and clearer (yes, don't laugh) than list(reversed(it[1:-2])).
This is because in a slice like -
list[start:stop:step]
start is inclusive, resultant list starts at index start.
stop is exclusive, that is the resultant list only contains elements till stop - 1 (and not the element at stop).
So for your caseit[1:-2] - the 1 is inclusive , that means the slice result starts at index 1 , whereas the -2 is exclusive , hence the last element of the slice index would be from index -3.
Hence, if you want the reversed of that, you would have to do it[-3:0:-1] - only then -3 would be included in the sliced result, and the sliced result would go upto 1 index.
The important things to understand in your slices are
Start will be included in the slice
Stop will NOT be included in the slice
If you want to slice backwards, the step value should be a negative value.
Basically the range which you specify is a half-open (half-closed) range.
When you say it[-3:0:-1] you are actually starting from the third element from the back, till we reach 0 (not including zero), step one element at a time backwards.
>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]
Instead, you can realize the start value like this
>>> it[len(it)-3 : 0 : -1]
[7, 6, 5, 4, 3, 2]
I think the other two answers disambiguate the usage of slicing and give a clearer image of how its parameters work.
But, since your question also involves readability -- which, let's not forget, is a big factor especially in Python -- I'd like to point out how you can improve it slightly by assigning slice() objects to variables thus removing all those hardcoded : separated numbers.
Your truncate and reverse slice object could, alternatively, be coded with a usage implying name :
rev_slice = slice(-3, 0, -1)
In some other config-like file. You could then use it in its named glory within slicing operations to make this a bit more easy on the eyes :
it[rev_slice] # [7, 6, 5, 4, 3, 2]
This might be a trivial thing to mention, but I think it's probably worth it.
Why not create a function for readability:
def listify(it, start=0, stop=None, rev=False):
if stop is None:
the_list = it[start:]
else:
the_list = it[start:stop]
if rev:
return the_list[::-1]
else:
return the_list
listify(it, start=1, stop=-2) # [2, 3, 4, 5, 6, 7]
listify(it, start=1, stop=-2, rev=True) # [7, 6, 5, 4, 3, 2]
A good way to intuitively understand the Python slicing syntax is to see how it maps to the corresponding C for loop.
A slice like
x[a:b:c]
gives you the same elements as
for (int i = a; i < b; i += c) {
...
}
The special cases are just default values:
a defaults to 0
b defaults to len(x)
c defaults to 1
Plus one more special case:
if c is negative, then a and b are swapped and the < is inverted to a >

Categories