I was trying to print a list in backwards order using a for loop, however my code only prints of a 1, any ideas why?
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(len(sorted_list)-2,-3,-1):
des_list.append(sorted_list[i-2])
des_list.append(sorted_list[i - 1])
des_list.append(sorted_list[i])
des_list.append(sorted_list[i+1])
print(des_list)
It would probably be easier to store the chunks of data into objects. That way, you can just call reversed() on the list of objects and handle the data that way.
If you want to keep the list in the format you have, you can loop through the list in "chunks", like this: for i in range(0, len(sorted_list), 4):.
So, for every 4 elements in the list, grab the chunk of of data using list slicing notation: sorted_list[i:i+4] and insert it to the front of the destination list.
Putting that together, you get this code:
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(0, len(sorted_list), 4):
des_list.insert(0, sorted_list[i:i+4])
print(des_list)
That will output this: [['sod', 3, 1, 0], ['tim', 5, 3, 1], ['bob', 0, 0, 10], ['jill', 4, 1, 0], ['jack', 4, 3, 1]].
Keep in mind that that code will give you a list of lists, because sorted_list[i:i+4] returns a list, which is why it might be easier to use objects instead.
If you don't want to have a list of lists, you can reverse the sliced list, loop through each element in the reversed sliced list, and insert it one at a time to the destination list.
Doing that, you get this code:
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(0, len(sorted_list), 4):
for j in reversed(sorted_list[i:i+4]):
des_list.insert(0, j)
print(des_list)
Which outputs this: ['sod', 3, 1, 0, 'tim', 5, 3, 1, 'bob', 0, 0, 10, 'jill', 4, 1, 0, 'jack', 4, 3, 1]
Related
How should I write the code with the following problem?
Implement the function reverse_print(lst) that prints out the contents of the given list ‘lst’
in reverse order. For example, given a list [3, 6, 2, 1], the output should be 1, 2, 6, 3 (vertical
printout allowed). For this code, you are only allowed to use a single for-loop. Without String Method
Also Not using Print[::-1]
Assuming you are not allowed to just call list.reverse() you can use range with a negative step to iterate the list in reverse order:
def reverse_print(lst):
out = []
for i in range(len(lst) - 1, -1, -1):
out.append(lst[i])
print(*out, sep=", ")
inp = [1, 2, 3, 4]
reverse_print(inp)
Output: 4, 3, 2, 1
You may try something like this
def reverse_print(lst):
rev = [lst[abs(i-l)-1] for i in range(l)]
return rev
lst = [3,6,2,1]
l = len(lst)
print(reverse_print(lst))
I would like to modify a list that has 3 different numbers [0, 1, 2]
Each 0 should be replaced with either the last 1 or 2 value depending on which was most recent during the iteration.
Is it possible to create the new list using a list comprehension?
I know I can use a for loop and just record the last 1 or 2 and append the values to the new list but I prefer the most pythonic way.
list = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
new_list = [1, 1, 2, 1, 1, 1, 1, 2, 2, 2]
I was using this but then realised that after 2 0s in a sequence it would start recording 0s again.
new_list = [list[index-1] if list[index] == 0 else value for index,value in enumerate(list)]
Starting in python 3.8 you now have the walrus operator := which can assign values as part of an expression and works in list comprehensions. You just need to decide what the first value will be if the list starts with 0 since there is no previous value:
alist = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
j = 0
[j:= i if i else j for i in alist]
# [1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
Perform that just with a list comprehension could be a little weird, so here my solution (without creating a new list):
my_list = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
last_not_zero = 0
for index, number in enumerate(my_list):
if number!=0:
last_not_zero = number
else:
my_list[index] = last_not_zero
print(my_list)
And you'll get:
[1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
If you have a large list or you are using Pandas in your code,
import pandas as pd
s = pd.Series(list)
s.replace(0, pd.np.nan).ffill().to_list()
Output
[1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
NOTE: If you are not using pandas/numpy in your code, then basic for loop would be the best way to do this. Advise using the above code only for large arrays with multiple manipulations.
How about this
last_value = 0
new_list = []
for value in list:
if value != 0:
last_value = value
new_list.append(value)
else:
new_list.append(last_value)
Depends on the condition.
In most cases, you can place the condition within the while loop in the if-else criteria statements.
If, say, you want to replace the content of a list if the previous value was
something,
size = len(list)
while True:
index = index + 1
if index!=0 and index<size:
if list[index-1]==something:
list[index] = value to be replaced
if index == (size-1):
a = 0
for a in (0, (size-1)):
print(a,":",list(a))
break
I need to randomly select elements from a list. Currently, I will sometimes select too many copies of an element from the original list eg:
Original List: [0, 1, 2, 3, 4]
3 Randomly Selected Elements: [4, 4, 4]
I do not want multiple 4s selected if there was only 1 in the original list.
What should I do to not take more copies of a value than exists in the first array?
A solution is to remove the elements from the original list when you select them.
import random
original_list = [1, 2, 2, 3, 3, 3]
number_of_random_selections = 4
random_selections = []
for i in range(0, len(original_list)):
random_index = random.randint(0, number_of_random_selections)
random_selection = original_list[random_index]
random_selections.append(random_selection)
original_list.remove(random_selection)
print(random_selections)
I want to make a function that takes a list of integers and replaces the elements in the list with their respective squares.
I tried reassigning every element by virtue of its position (index) in the list, but for some reason the second element in the list gets squared twice.
def square_list(list1):
for i in list1:
list1[list1.index(i)] = i**2
print(list1)
square_list([1, 2, 3, 4, 5])
I expect the printed list to be [1, 4, 9, 16, 25] since the list I'm testing the function with is [1, 2, 3, 4, 5].
If a function is required to square list elements in-place, use it:
def square_list(list_1):
for i in range(len(list_1)):
list_1[i] = list_1[i]**2
my_list = [1, 2, 3, 4, 5]
square_list(my_list)
print(my_list)
Since the function doesn't return anything, square_list([1, 2, 3, 4, 5]) is useless.
Python's map built-in function is good for this, so you don't really have to write your own function.
l = [1, 2, 3, 4, 5]
l = list(map(lambda x: x**2, l))
Let us say we have a list of integers:
list = [6, 4, 1, 4, 4, 4, 4, 4, 2, 1]
I now wrote a function which returns another list with all the integers from the list above without repeats.
def no_repeats(s):
new_list = []
for number in s:
if new_list.count(number) < 1:
new_list.append(number)
return(new_list)
The new_list returns [6, 4, 1, 2] which is good! My question is how I would now write two similar functions:
A function clean(s) which does not return a new list like the function above, but changes the original list by deleting all the numbers that repeat. Thus, the result has to be the same and the function must not include "return" or create a new list. It must only clean the original list.
A function double(s) which, again, changes the original list (does not return a new list!) but this time, by doubling every number in the original list. Thus, double(list) should change the original list above to:
[6, 6, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1]
Thank you for all the help!
Removing duplicates inplace without preserving the order:
def no_repeats(L):
L[:] = set(L)
There are several variations possible (preserve order, support non-hashable items, support item that do not define total ordering) e.g., to preserve order:
from collections import OrderedDict
def no_repeats(L):
L[:] = OrderedDict.fromkeys(L)
To double each element's value inplace:
def double(L):
for i in range(len(L)):
L[i] *= 2
To duplicate each element:
def duplicate_elements(L):
L[:] = [x for x in L for _ in range(2)]
>>> def clean(s):
... s[:] = [s[i] for i in range(len(s)) if s[i] not in s[:i]]
...
>>> st = [1, 2, 3, 2, 1]
>>> clean(st)
>>> st
[1, 2, 3]
>>> def double(s):
... s[:] = [s[i//3] for i in range(3*len(s)) if i % 3]
...
>>> st = [1, 2, 3, 2, 1]
>>> double(st)
>>> st
[1, 1, 2, 2, 3, 3, 2, 2, 1, 1]
neither is particularly efficient nor pythonic, yet do address the OP question
def double(s):
... s[:] = [s[i//2] for i in range(2*len(s))]
will also do the trick, with a little less obsfucation