Count elements in nested list - python

The following python code should make it clear what i'd like to accomplish.
# Say I have the following list and I want to keep count of 1's while going through each nested list
L = [[1,1,0,0,0,1],[1,1,0,0,0,0],[0,0,0,0,0,1],[1,1,1,1,1,1]]
# So I'd like to get a list containing [3, 5, 6, 12]
# I tried to find a compact way of doing this by mapping this list into a another list like such
T = [L[:i].count(1) for i in range(len(L))]
# >>> [0, 0, 0, 0]
# But this doesn't work so how to count occurances for nested lists?
# Is there a compact way of doing this (maybe with Lambda functions)?
# I'd like to avoid using a function like:
def Nested_Count():
Result = []
count = 0
for i in L:
count += i.count(1)
Result.append(count)
return Result
# >>> [3, 5, 6, 12]
Please let me know if it's possible or not to have a more compact code to do this.
Thanks!

[sum([x.count(1) for x in L[:i]]) for i in range(1, len(L) + 1)]
should do what you want.

Use sum and a list comprehension.
L = [[1,1,0,0,0,1],[1,1,0,0,0,0],[0,0,0,0,0,1],[1,1,1,1,1,1]]
L2 = [sum(x) for x in L]
T = [sum(L2[:x+1]) for x in xrange(len(L2))]

Related

How do I move list elements to another list if a condition is met?

I have a list of values and I want to move certain (or all) values to another list if they exist in a reference list.
x = [2,3,4,5,6,7,8] # list of values
ref = [2,3,4,5,6,7,8] # reference list
result = [x.pop(i) for i, v in enumerate(x) if v in ref]
But because of popping the current index, it ends up giving every other value instead. Is there a nice straightforward way to do this?
What I want at the end of this example is x=[] and result=[2,3,4,5,6,7,8], but ref doesn't need to contain all elements of x, this was just for an example. In another case it might be:
x = [2,3,4,5,6,7,8] # list of values
ref = [2,6,7] # reference list
So then I want x = [3,4,5,8] and result = [2,6,7]
In general, we should avoid modifying objects while iterating over them.
For this problem, we could generate result and filter x in two steps using comprehensions (avoiding appending to lists) as in the following example.
result, x = [v for v in x if v in ref], [v for v in x if v not in ref]
You could do it the old-fashioned way, with a while loop and a pointer into x:
x = [2, 3, 4, 5, 6, 7, 8]
ref = [2, 6, 7]
result = []
i = 0
while i < len(x):
if x[i] in ref:
result.append(x.pop(i))
else:
i += 1
print(x)
print(result)
Output:
[]
[2, 3, 4, 5, 6, 7, 8]
You can simply iterate from the end to the start to avoid pop() changing the list size while iterating. Just call reverse() on your new list after running your loop if the order of the list matters.

Filter elements of a list in Python

I would like to filter the elements of a given list.
I have an integer and I would like to only keep the numbers in a list which all characters are less than that number. (Now it is 5). I can write a longer code for this, but I would like to have a 1 line code using filter() .
I only got this far:
def fil(l):
return list(filter(lambda x: x<5, [int(s) for i in l for s in str(i)]))
for l = [1,2,4,8,12] it should give back:
[1, 2, 4, 12]
But it returns this:
[1, 2, 4, 1, 2]
Can you help me fix this?
Without using filter This might help :
l = [1,2,4,8,12]
results = [item for item in l if all(int(x) < 5 for x in str(item))]
If you want necessarily use filter and your function fil then you have :
def fil(l):
return list(filter(lambda item: all(int(x) < 5 for x in str(item)), l))

How to remove all repeating elements from a list in python?

I have a list like this:-
[1,2,3,4,3,5,3,6,7,8]
I want to remove the repeating element (here:- 3) completely from the list like this:-
[1,2,4,5,6,7,8]
How do I implement this in python such that not only the first occurrence of duplicate element is removed but all the duplicating values are removed
You can use Counter from collections to count the number of occurrences and select those elements which appear exactly once using a list comprehension:
from collections import Counter
a = [1,2,3,4,3,5,3,6,7,8]
[k for k, v in Counter(a).items() if v == 1]
(Counter basically returns a dictionary where elements are stored as keys and their counts are stored as values.)
This code should work
#Finding duplicate
def dup(x):
s = len(x)
duplicate = []
for i in range(s):
k = i + 1
for j in range(k, s):
if x[i] == x[j] and x[i] not in duplicate:
duplicate.append(x[i])
return duplicate
#begining
list1 = [1, 2, 3, 4, 3, 5, 3, 6, 7, 8]
#Finding duplicate
dup_list = (dup(list1))
#removing duplicates from the list
final_list = list(set(list1) - set(dup_list))
print(final_list)
A good and efficient way will be to use pandas
import pandas as pd
sample_list = [1,2,3,4,3,5,3,6,7,8]
unique_list = list(pd.Series(sample_list).drop_duplicates())
>> unique_list
>> [1, 2, 3, 4, 5, 6, 7, 8]
Use a set. To get rid of all repeating values use this:
a = [1,2,3,4,3,5,3,6,7,8]
print(a)
a = list(set(a))
print(a)
That will output
[1,2,3,4,3,5,3,6,7,8]
[1,2,4,5,6,7,8]

Leave parts of the instructions blank for python to complete

I'm new to Python so I don't know if this is possible, but my guess is yes. I want to iterate over a list and put items into new lists according to their value. For instance, if item_x == 4, I would want to put it in a list called list_for_4. The same is true for all other items in my list and numbers 0 to 10. So is it possible to generalize a statement in such a way that if item_x == *a certain value*, it will be appended to list_for_*a certain value*?
Thanks!
Maybe use list comprehension with if statement inside?
Like:
list_for_4 = [x for x in my_list if x==4]
And combine it with a dict.
With a simple iteration through the list:
lst_for_1 = []
lst_for_2 = []
lst_for_3 = []
d = {1: lst_for_1, 2: lst_for_2, 3: lst_for_3}
for x in lst:
d[x].append(x)
Or, if you want a condition that is more complicated than just the value of x, define a function:
def f(x):
if some condition...:
return lst_for_1
elif some other condition:
return lst_for_2
else:
return lst_for_3
Then replace d[x].append(x) by f(x).append(x).
If you don't want to do the iteration yourself, you could also use map:
list(map(lambda x: d[x].append(x),lst))
or
list(map(lambda x: f(x).append(x),lst))
The version with map will return an list of Nones that you don't care about. map(...) returns an iterator, and as long as you do not iterate through it (for example, to turn its result into a list), it will not perform the mapping. That's why you need the list(map(...)), it will create a dummy list but append the items of lst to the right lists on the way, which is what you want.
Don't know why you want to do it. But you can do it.
data = [1, 2, 3, 4, 1, 2, 3, 5]
for item in data:
name = f'list_for_{item}'
if name in globals():
globals()[name].append(item)
else:
globals()[name] = [item]
Instead of trying to generate a dynamic variables. A map using a dictionary structure might help you.
For example:
from collections import defaultdict
item_list = [1, 2, 3, 9, 2, 2, 3, 4, 4]
# Use a dictionary which elements are a list by default:
items_map = defaultdict(list)
for i in item_list:
items_map['list_for_{}'.format(i)].append(i)
print(items_map)
# Test the map for elements in the list:
if 'list_for_4' in items_map:
print(items_map['list_for_4'])
else:
print('`list_for_4` not found.')
Alternatively if you only require the number of times an item occurs in the list you could aggregate it using Counter:
from collections import Counter
item_list = [1, 2, 3, 9, 2, 2, 3, 4, 4]
result = Counter(item_list)
print(result)

Python arranging a list to include duplicates

I have a list in Python that is similar to:
x = [1,2,2,3,3,3,4,4]
Is there a way using pandas or some other list comprehension to make the list appear like this, similar to a queue system:
x = [1,2,3,4,2,3,4,3]
It is possible, by using cumcount
s=pd.Series(x)
s.index=s.groupby(s).cumcount()
s.sort_index()
Out[11]:
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
dtype: int64
If you split your list into one separate list for each value (groupby), you can then use the itertools recipe roundrobin to get this behavior:
x = ([1, 2, 2, 3, 3, 3, 4, 4])
roundrobin(*(g for _, g in groupby(x)))
If I'm understanding you correctly, you want to retain all duplicates, but then have the list arranged in an order where you create what are in essence separate lists of unique values, but they're all concatenated into a single list, in order.
I don't think this is possible in a listcomp, and nothing's occurring to me for getting it done easily/quickly in pandas.
But the straightforward algorithm is:
Create a different list for each set of unique values: For i in x: if x not in list1, add to list 1; else if not in list2, add to list2; else if not in list3, ad to list3; and so on. There's certainly a way to do this with recursion, if it's an unpredictable number of lists.
Evaluate the lists based on their values, to determine the order in which you want to have them listed in the final list. It's unclear from your post exactly what order you want them to be in. Querying by the value in the 0th position could be one way. Evaluating the entire lists as >= each other is another way.
Once you have that set of lists and their orders, it's straightforward to concatenate them in order, in the final list.
essentially what you want is pattern, this pattern is nothing but the order in which we found unique numbers while traversing the list x for eg: if x = [4,3,1,3,5] then pattern = 4 3 1 5 and this will now help us in filling x again such that output will be [4,3,1,5,3]
from collections import defaultdict
x = [1,2,2,3,3,3,4,4]
counts_dict = defaultdict(int)
for p in x:
counts_dict[p]+=1
i =0
while i < len(x):
for p,cnt in counts_dict.items():
if i < len(x):
if cnt > 0:
x[i] = p
counts_dict[p]-=1
i+=1
else:
continue
else:
# we have placed all the 'p'
break
print(x) # [1, 2, 3, 4, 2, 3, 4, 3]
note: python 3.6+ dict respects insertion order and I am assuming that you are using python3.6+ .
This is what I thought of doing at first but It fails in some cases..
'''
x = [3,7,7,7,4]
i = 1
while i < len(x):
if x[i] == x[i-1]:
x.append(x.pop(i))
i = max(1,i-1)
else:
i+=1
print(x) # [1, 2, 3, 4, 2, 3, 4, 3]
# x = [2,2,3,3,3,4,4]
# output [2, 3, 4, 2, 3, 4, 3]
# x = [3,7,1,7,4]
# output [3, 7, 1, 7, 4]
# x = [3,7,7,7,4]
# output time_out
'''

Categories

Resources