Delete even indexes out of range [duplicate] - python

I'm trying to remove the odd-indexed elements from my list (where zero is considered even) but removing them this way won't work because it throws off the index values.
lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
def remove_odd_elements(lst):
i=0
for element in lst:
if i % 2 == 0:
pass
else:
lst.remove(element)
i = i + 1
How can I iterate over my list and cleanly remove those odd-indexed elements?

You can delete all odd items in one go using a slice:
del lst[1::2]
Demo:
>>> lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
>>> del lst[1::2]
>>> lst
['712490959', '623726061', '552157404', '1285252944', '1130181076', '552157404', '545600725']
You cannot delete elements from a list while you iterate over it, because the list iterator doesn't adjust as you delete items. See Loop "Forgets" to Remove Some Items what happens when you try.
An alternative would be to build a new list object to replace the old, using a list comprehension with enumerate() providing the indices:
lst = [v for i, v in enumerate(lst) if i % 2 == 0]
This keeps the even elements, rather than remove the odd elements.

Since you want to eliminate odd items and keep the even ones , you can use a filter as follows :
>>>filtered_lst=list(filter(lambda x : x % 2 ==0 , lst))
this approach has the overhead of creating a new list.

Related

simpler(save memory) way to get all possible combinations in order of increasing length

I am trying to get all the possible combinations of listA in order of increasing length. This is easy to do, but the current code I have returns Memory error once my list goes above 1000. How do I do the same with a code that does not use as much memory.
original_list = ['1', '2', '3', '4']
#code:
modified_list= [original_list[i:j + 1] for i in range(len(original_list)) for j in range(i + 1, len(original_list))]
print(modified_list)
#output:
#nodified_list = [['1', '2'],['1', '2', '3'],['1', '2', '3', '4'],
['2', '3'],['2', '3', '4'],['3', '4']]
I saw a similar code but this one prints all the combinations of all the elements inside the list.
import itertools
List = []
for L in range(0, len(original_list)+1):
for subset in itertools.combinations(original_list, L):
subset = str(subset).replace('(','[').replace(')',']') #.replace(',','')
List.append(subset)
it's most probably that your modified list that takes up the memory...
try to print the [original_list[i:j + 1] without saving it in another list.
that shouldn't take more memory than your original list size.
Generator expression saves memory a lot, instead of list you can use this:
subsets = (original_list[i:j + 1] for i in range(len(original_list)) for j in range(i + 1, len(original_list)))
Also if you want to print, iterate through each element, do not convert to list.
for i in subsets:
print(i)

How to compare each element of multiple lists and return name of lists which are different

I am having multiple lists and I need to compare each list with one another and return the name of lists which are different. We need to consider value of elements in list irrespective of their position while comparing lists.
For example:-
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
Output:-
['Lis1','Lis2','Lis3','Lis4']
Thanks in advance.
Try this:
input_lists = {"Lis1": ['1', '2', '3'], "Lis2": ['1', '2'],
"Lis3": ['0', '1', '3'], "Lis4": [], "Lis5": ['1', '2']}
output_lists = {}
for k, v in input_lists.items():
if sorted(v) not in output_lists.values():
output_lists[k] = sorted(v)
unique_keys = list(output_lists.keys())
print(unique_keys) # ['Lis1', 'Lis2', 'Lis3', 'Lis4']
import itertools
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
k=[Lis1,Lis2,Lis3,Lis4,Lis5]
k.sort()
list(k for k,_ in itertools.groupby(k))
output
[[], ['0', '1', '3'], ['1', '2'], ['1', '2', '3']]
a simple way to implement
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
lis=[Lis1,Lis2,Lis3,Lis4,Lis5]
final=[]
for ele in lis:
if(ele not in final):
final.append(ele)
print(final)
with your given data you can use:
Lis1=['1','2','3']
Lis2=['1','2']
Lis3=['0','1','3']
Lis4=[]
Lis5=['1','2']
name_lis = {'Lis1': Lis1, 'Lis2': Lis2, 'Lis3': Lis3, 'Lis4': Lis4, 'Lis5': Lis5}
tmp = set()
response = []
for k, v in name_lis.items():
s = ''.join(sorted(v))
if s not in tmp:
tmp.add(s)
response.append(k)
print(response)
output:
['Lis1', 'Lis2', 'Lis3', 'Lis4']
name_lis dictionary contains the name of your list and the actual list, you are iterating over each list, and for each list, you are sorting the elements and then converting in a string, if the string was encountered before you know that the list is a duplicate if not you are adding the list to the response

Python list insert with index

I have an empty python list. and I have for loop that insert elements with index but at random (means indices are chosen randomly to insert the item). I tried a simple example, with randomly select indices, but it works in some indices but others won't work. Below is a simple example of what I wanna do:
a=[]
#a=[]
a.insert(2, '2')
a.insert(5, '5')
a.insert(0, '0')
a.insert(3, '3')
a.insert(1, '1')
a.insert(4, '4')
The output of this is a = ['0','1','2','5','4','3']
it's correct in the first three (0,1,2) but wrong in the last three ('5','4','3')
How to control insert to an empty list with random indices.
list.insert(i, e) will insert the element e before the index i, so e.g. for an empty list it will insert it as the first element.
Map out the operations in your head using this information:
a = [] # []
a.insert(2, '2') # ['2']
a.insert(5, '5') # ['2', '5']
a.insert(0, '0') # ['0', '2', '5']
a.insert(3, '3') # ['0', '2', '5', '3']
a.insert(1, '1') # ['0', '1', '2', '5', '3']
a.insert(4, '4') # ['0', '1', '2', '5', '4', '3']
Keep in mind that lists are not fixed sized arrays. The list has no predefined size, and can grow and shrink by appending or popping elements.
For what you might want to do you can create a list and use indexing to set the values.
If you know the target size (e.g. it is 6):
a = [None] * 6
a[2] = '2'
# ...
If you only know the maximum possible index, it would have to be done like this:
a = [None] * (max_index+1)
a[2] = '2'
# ...
a = [e for e in a if e is not None] # get rid of the Nones, but maintain ordering
If you do not know the maximum possible index, or it is very large, a list is the wrong data structure, and you could use a dict, like pointed out and shown in the other answers.
If your values are unique, could you use them as keys in a dictionary, with the dict values being the index?
a={}
nums = [1,4,5,7,8,3]
for num in nums:
a.update({str(num): num})
sorted(a, key=a.get)
If you have an empty array and you try to add some element in the third position, that element will be added in first position. Because python's list is a linked list.
You could resolve your problem creating a list with None values in it. This could be made with this:
# Creating a list with size = 10, so you could insert up to 10 elements.
a = [None] * 10
# Inserting the 99 in third position
a.insert(3,99)
Another way to do that is using numpy:
import numpy as np
# Create an empty array with 10 elements
a = np.empty(10,dtype=object)
# Insert 99 number in third position
np.insert(a, 3, 99)
print(a)
# array([None, None, None, 99, None, None, None, None, None, None, None],
# dtype=object)

Subtract items in a single list and retrieve items that match a condition

I recently asked a question regarding the retrieval of differences between two lists that meet a condition, but I keep failing to alter the EXAMPLE LAMBDA EXPRESSION below to do the same for the items in a single list:
A = ['12', '15', '20', '30']
filter(lambda a: all([abs(int(a) - int(b)) >= 5 for b in List1]), List2)
Where my list is sorted and can have varied lengths. The goal is to change the above expression in order to retrieve only those items with a difference TO ANY OTHER ITEM in the list is less than or equal to 5.
Where the output working on the list above should be:
newAList = ['12', '15', '20']
This is a shorter version:
>>> A = ['12', '15', '20', '30']
>>> [x for x in A if len(A) == 1 or filter(lambda y: 0 < abs(int(y) - int(x)) <= 5,A)]
['12', '15', '20']
>>>
Based on your comments, I believe the following list comprehension should do what you are looking for. The key parts are:
Using any instead of all to check whether any item exists that is at most 5 smaller or larger than the current one being looked at
Using enumerate to ensure the condition ignores the item currently being looked at - you can remove the calls to enumerate and change the comparison to 0 < abs(int(a) - int(b)) <= 5 if you know there are no duplicates
Using a list comprehension instead of filter to make it more readable, in my opinion (only just) - it should be possible to do the same thing with filter, however
The code:
>>> A = ['12', '15', '20', '30']
>>> [a for i, a in enumerate(A) if any(j != i and abs(int(a) - int(b)) <= 5 for j, b in enumerate(A))]
['12', '15', '20']
I bet this will be quite inefficient for any list much larger than this one, however, since you will be iterating over the list once for every item in the list. Hopefully it is enough to give you a starting point, however.

Altering list while iterating

Python noob here. I have a list of numbers represented as strings. Single digit numbers are represented with a zero and I'm trying to get rid of the zeroes. For instance, ['01', '21', '03'] should be ['1', '21', '3'].
My current solution seems a bit clumsy:
for item in list:
if item[0] == '0':
list[list.index(item)] = item[1]
I'm wondering why this doesn't work:
for item in list:
if item[0] == '0':
item = item[1]
Rebinding the iterating name does not mutate the list.
Also:
>>> [str(int(x, 10)) for x in ['01', '21', '03']]
['1', '21', '3']
You could try stripping the zero:
>>> map(lambda x: x.lstrip('0'), ['001', '002', '030'])
['1', '2', '30']
To mutate the list:
for i, item in enumerate(mylist):
if item.startswith('0'):
mylist[i] = item[1:]
Better is probably just to create a new list:
new_list = [x.lstrip('0') for x in mylist]
Your code doesn't work because assigning to item merely gives the name item a new value, it doesn't do anything to the old value of item.
The code "item" is a variable that contains the value of the item as you iterate through the list. It has no reference to the list itself.
Your first solution is very slow because it will have to search the list for each item to find the index.
See other answers for examples of how to accomplish what you want.

Categories

Resources