How can one make a list contain only unique items while preserving order AND updating it in-place?
I know that a set can be used, but it will not guarantee ordering.
Use a supporting set, and a while loop:
def unique(arr):
tmp_set = set()
i = 0
while i < len(arr):
if arr[i] in tmp_set:
del arr[i]
else:
tmp_set.add(arr[i])
i += 1
The above will update the array in-place, and preserve ordering of the elements as well.
another way without sets:
def deduplicate_in_place(items):
_tmp_list = []
for item in items:
if item not in _tmp_list:
_tmp_list.append(item)
items[:] = _tmp_list
Enhanced CodeSpeed solution.
lst = [1, 2, 2, 1, 1]
seen = set()
length = len(lst) - 1
i = 0
while i < length:
if lst[i] in seen:
del lst[i]
i -= 1
seen.add(lst[i])
i += 1
length = len(lst)
print(lst)
You can use a loop to iter over the entries in the list one by one and insert them into a newlist only if they are not present in the new list.
lst = [3,3,3,1,2,2,4]
my_list = []
for i in lst:
if i not in my_list:
my_list.append(i)
my_list
# Output - [3, 1, 2, 4]
I hope this helps.
Related
How do we calculate with having both int element and list of list element.
def minelementNested(list):
minele = list[0]
sumele = 0
count = 0
for i in list1:
if type(i) is int:
sumele = sumele+i
if i < minele:
minele = i
count = count +1
else:
sumele += sum(i)
count = count + len(i)
else_min = min(i)
if else_min < minele:
minele = else_min
avg = sumele/count
print(avg)
return minele
list1 = [23,24,[10,11,12],56,85,[34,45,6]]
minelementNested(list1)
Is there any other way to do this?
or can we convert the individual int element to list and go ahead with list comprehension.
please suggest.
Thank you.
If you only have one level of nested list to worry about, you can do this as a one-liner that normalizes the nested list to a 2D list of lists of ints, and then unpacks it in a nested generator:
>>> nums = [23,24,[10,11,12],56,85,[34,45,6]]
>>> min(n for i in nums for n in (i if isinstance(i, list) else [i]))
6
If you have arbitrary levels of nesting, use a recursive function:
>>> def nested_min(arr):
... if isinstance(arr, int):
... return arr
... return min(nested_min(i) for i in arr)
...
>>> nested_min(nums)
6
>>> nested_min([10, 11, 12, [[1, 2], 3, 4], 5])
1
I have to take a list such as [2,2,0,2] and I then need to return a new list of the indexes for the elements in the list that are not 0 so for the list of [2,2,0,2] I would need to return [0,1,3]. Or for [1,0,1,1] I would need to return [0,2,3].
def test(B):
for k in list(B):
if k > 0:
result = []
for i in range(len(B)):
result.append(i)
return result
test([2,2,0,2])
->[0,1,2,3]
My issue is that all of the indexes get returned and I have tried to fix this but have had no luck. If anyone could help that'd me great, thanks.
You can use enumerate to achieve this neatly:
def legal(B):
return [i for i, x in enumerate(B) if x]
# or if you want to cover more than numbers
# return [i for i, x in enumerate(B) if x != 0]
>>> legal([2,2,0,2])
[0, 1, 3]
>>> legal([1,0,1,1])
[0, 2, 3]
this should do the work :
def indices(some_list):
indices_list = []
for i in range(0, len(some_list)):
if some_list[i] != 0:
indices_list.append(i)
return indices_list
you can use list comprehension like below
ls = [2,2,0,2]
ind = [i for i, val in enumerate(ls) if val!=0]
print(ind)
You could try this:
def legal(B):
result = []
for i, k in enumerate(list(B)):
if k > 0:
result.append(i)
return result
Why are you doing list(B)? If B is not a list then this should work. If it is you should remove the list function.
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
Here I want to find lists in A which sum of all sublists in list not grater than 5.
Which the result should be [[1,4],[2,3]]
I tried a long time to solve this problem in python. But I still can't figure out the right solution, which I stuck at loop out multiple loops. My code as follows, but its obviously wrong, how to correct it?
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
z = []
for l in A:
for list in l:
sum = 0
while sum < 5:
for i in list:
sum+=i
else:
break
else:
z.append(l)
print z
Asking for help~
Simplification of #KindStranger method in a one-liner:
>> [sub for x in A for sub in x if max(sum(sub) for sub in x) <= 5]
[[1, 4], [2, 3]]
A simple solution which you can think of would be like this -
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
r = [] # this will be our result
for list in A: # Iterate through each item in A
f = True # This is a flag we set for a favorable sublist
for item in list: # Here we iterate through each list in the sublist
if sum(item) > 5: # If the sum is greater than 5 in any of them, set flag to false
f = False
if f: # If the flag is set, it means this is a favorable sublist
r.append(list)
print r
But I'm assuming the nesting level would be the same. http://ideone.com/hhr9uq
This should work for your problem:
>>> for alist in A:
... if max(sum(sublist) for sublist in alist) <= 5:
... print(alist)
...
[[1, 4], [2, 3]]
The one with all()
[t for item in A for t in item if all(sum(t)<=5 for t in item)]
I am trying to make a list that takes in numbers and removes all the old numbers in the list and returns s the result, but it keeps on giving me the error "local variable 's' referenced before assignment" How do I fix it?
def purify(lst):
for item in lst:
if item%2 != 0:
lst.remove(item)
s.append(lst)
s = []
return s
It isn't clear why you want to return a list containing a single list. Why not just return the "purified" list?
def purify(lst):
return [item for item in lst if item % 2 == 0]
This uses a list comprehension. Demo:
>>> purify([1, 2, 3, 4, 5])
[2, 4]
For more flexibility, you could also make a version where you pass your own rule:
def purify(lst, rule):
return [item for item in lst if rule(item)]
Demo:
>>> purify([1, 2, 3, 4, 5], lambda i: i % 2)
[1, 3, 5]
You need to assign s to empty list first and then append.
def purify(lst):
for item in lst:
if item%2 != 0:
lst.remove(item)
s = []
s.append(lst)
return s
As #jonrsharpe suggested, don't remove the item while iterating over list. The good approach is using the list comprehension:
[i for i in lst if i%2!=0]
You should not remove items while iterating, because the list should not be changed when using iterators (this is what you do with "in").
def purify(lst):
s = []
for item in lst:
if item%2 == 0:
s += [item]
return s
btw: This can be done very fast with numpy.
import numpy as np
...
def purify(lst):
indices = np.where(np.mod(lst,2) == 0)
return np.array(lst)[indices]
Simplify your life with filter:
filter(lambda x: x % 2 == 0, range(5))
What i have only removes duplicated items and sorts them. I need to remove one instance of every item and return a new list with the items in it. This is what i have:
def rem(nlst):
n = []
for x in nlst:
if x not in n:
n.append(x)
n.sort()
return n
This is what it should do:
>>> rem([4])
[]
>>> rem([4,4])
[4]
>>> rem([4, 1, 3, 2])
[]
>>> rem([2, 4, 2, 4, 4])
[2, 4, 4]
An easy implementation is to use collections.Counter:
def rem(iterable):
c = collections.Counter(iterable)
for k in c:
c[k] -= 1
return sorted(c.elements())
In Python versions before 2.7, collections.Counter is not available. You can use a set to record the items you already saw instead:
def rem(iterable):
result = []
seen = set()
for x in iterable:
if x in seen:
result.append(x)
else:
seen.add(x)
result.sort()
return result
A slight tweak to your code seems to work ok. Just added a variable to track the current value and only append a new one if you have already seen that value:
def rem(nlist):
n = []
nlist.sort()
cur = None
for x in nlist:
if x == cur:
n.append( x )
cur = x
return n
~