In this script I have used both list comprehension and for. I need to replace for loop with comprehension and add this solve inside list comprehension.
How can add
for i in k:
count_list.append(l.count(i))
inside this block
pairs = [int(pair/2) for pair in count_list if int(pair/2) != 0]
My code:
def sockMerchant(ar):
l = ar
k = set(l)
count_list = []
for i in k:
count_list.append(l.count(i))
pairs = [int(pair/2) for pair in count_list if int(pair/2) != 0]
return sum(pairs)
n = int(input().strip())
ar = list(map(int, input().strip().split(' ')))
result = sockMerchant(ar)
print(result)
You should not be using a list comprehension at all, nor the for loop you have now. The loop is inefficient; by using list.count() you are traversing the whole list l for every unique value, creating a O(N^2) loop.
Use a collections.Counter() object instead and count in O(N) time:
from collections import Counter
def sockMerchant(ar):
counts = Counter(ar)
return sum(count//2 for count in counts.values())
or even
def sockMerchant(ar):
return sum(count//2 for count in Counter(ar).values())
if you insist on a single line.
Note that sum() doesn't mind a few 0 values here and there, so I removed the if test for single 'socks'. Also, I used the // floor division operator rather than turning the floating point result of dividing by 2 back into an integer.
Related
I need to write a code that Given a list of numbers return a list in which all
equal adjacent elements have been reduced
to a single element.
example:
list=[1,1,3,4,5,5,6,7,7,7,8,5,7]
becomes
[1,3,4,5,6,7,8,5,7]
i wrote this code:
list = []
list1 = []
for i in range(10):
c = input("inserisci un numero: ")
list.append(c)
k = 0
for i in range(len(list)-1):
if list[i+1] != list[i]:
list1[k].append(list[i])
k+=1
print(list1)
ut it's giving me index error could you explain me why?
You want list1.append(list[i]), not list1[k]. The k variable is useless.
The reason it explodes is that, the first time through the second loop, you refer to list1[0], but list1 is empty. It has no elements, so index 0 is out of bounds.
Add the first element to result list
result.append(list[0])
then just loop from 1 to the end of the original list.
On each iteration just check if list[i-1] != list[i]: if true add to result list like this result.append(list[i])
Using itertools.groupby function from the standard library you can group similar terms.
import itertools as it
l = [1,1,3,4,5,5,6,7,7,7,8,5,7]
ll = []
_ = [ll.append(next(grp)) if check else ll.append(grp) for check, grp in it.groupby(l)]
print(ll)
I need to turn this into a list comprehension. I have been stuck for a while. Any Ideas?
result = []
for i in range(length + 1):
m = number * i
result.append(m)
del result[0]
return result
You can do this -
[number*i for i in range(length+1)][1:]
This iterates over the range(length+1) multiplying each to the number and storing in a list. Then I just take all the elements except the 0th.
You can start iterating from 1 to avoid generate 0th element in the first place, as suggested by #wwii
[number*i for i in range(1,length+1)] #or simply range(length)
I was solving this leetcode problem - https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
I solved it easily by using nested for loops but list comprehensions have always intrigued me. Ive spent a lot of time to make that one liner work but I always get some syntax error.
here's the solution:
count = 0
ans = []
for i in nums:
for j in nums:
if i > j:
count = count + 1
ans.append(count)
count = 0
return ans
these were the ones so far I think shouldve worked:
return [count = count + 1 for i in nums for j in nums if i > j]
return [count for i in nums for j in nums if i > j count = count + 1]
return [count:= count + 1 for i in nums for j in nums if i > j]
Ill also be happy if there's some resource or similar to put it together, Ive been searching the python docs but didnt find something that'll help me
I will transform the code step by step in order to show the thought process.
First: we don't care what the value of count is afterward, but we need it to be 0 at the start of each inner loop. So it is simpler logically to set it there, rather than outside and then also at the end of the inner loop:
ans = []
for i in nums:
count = 0
for j in nums:
if i > j:
count = count + 1
ans.append(count)
return ans
Next, we focus on the contents of the loop:
count = 0
for j in nums:
if i > j:
count = count + 1
ans.append(count)
A list comprehension is not good at math; it is good at producing a sequence of values from a source sequence. The transformation we need to do here is to put the actual elements into our "counter" variable1, and then figure out how many there are (in order to append to ans). Thus:
smaller = []
for j in nums:
if i > j:
smaller.append(j)
ans.append(len(smaller))
Now that the creation of smaller has the right form, we can replace it with a list comprehension, in a mechanical, rule-based way. It becomes:
smaller = [j for j in nums if i > j]
# ^ ^^^^^^^^^^^^^ ^^^^^^^^
# | \- the rest of the parts are in the same order
# \- this moves from last to first
# and then we use it the same as before
ans.append(len(smaller))
We notice that we can just fold that into one line; and because we are passing a single comprehension argument to len we can drop the brackets2:
ans.append(len(j for j in nums if i > j))
Good. Now, let's put that back in the original context:
ans = []
for i in nums:
ans.append(len(j for j in nums if i > j))
return ans
We notice that the same technique applies: we have the desired form already. So we repeat the procedure:
ans = [len(j for j in nums if i > j) for i in nums]
return ans
And of course:
return [len(j for j in nums if i > j) for i in nums]
Another popular trick is to put a 1 in the output for each original element, and then sum them. It's about the same either way; last I checked the performance is about the same and I don't think either is clearer than the other.
Technically, this produces a generator expression instead. Normally, these would be surrounded with () instead of [], but a special syntax rule lets you drop the extra pair of () when calling a function with a single argument that is a generator expression. This is especially convenient for the built-in functions len and sum - as well as for any, all, max, min and (if you don't need a custom sort order) sorted.
Hmm, three people write sum solutions but every single one does sum(1 for ...). I prefer this:
[sum(j < i for j in nums) for i in nums]
Instead of trying to advance an external counter, try adding ones to your list and then sum it:
for example:
nums = [1,2,3,4,5]
target = 3
print(sum(1 for n in nums if n < target))
Using counter inside the list comprehension creates the challenge of resetting it's value, each iteration of the first loop.
This can be avoided by filtering, and summing, in the second loop:
You use the first loop to iterate over the values of nums array.
return [SECOND_LOOP for i in nums]
You use the second loop, iterating over all elements of nums array. You filter in the elements that are smaller than i, the current element in the first loop, with if i < j, and evaluating 1 for each of them. Finally, you sum all the 1s generated:
sum(1 for j in nums if i > j)
You get the number of values that meet the requirements, by the list comprehension of the first loop:
return [sum(1 for j in nums if i > j) for i in nums]
This solution has been checked & validated in LeetCode.
You need a slightly different approach for the inner loop than a list comprehension. Instead of repeatedly appending a value to a list you need to repeatedly add a value to a variable.
This can be done in a functional way by using sum and a generator expression:
count = 0
# ...
for j in nums:
if i > j:
count = count + 1
can be replaced by
count = sum(1 for j in nums if i > j)
So that we now have this:
ans = []
for i in nums:
count = sum(1 for j in nums if i > j)
ans.append(count)
return ans
This pattern can in fact be replaced by a list comprehension:
return [sum(1 for j in nums if i > j) for i in nums]
Alternative Solution
We can also use the Counter from collections:
class Solution:
def smallerNumbersThanCurrent(self, nums):
count_map = collections.Counter(nums)
smallers = []
for index in range(len(nums)):
count = 0
for key, value in count_map.items():
if key < nums[index]:
count += value
smallers.append(count)
return smallers
How do i write a list comprehension in python with an inclusion of a
count = count + 1?
print sum([info[count]["count"] for i in info])
# This is the working loop:
count = 0
lst = []
for i in info:
num = info[count]["count"]
# print num
count = count + 1
lst.append(num)
print sum(lst)
>>> a = ['a','b','c']
>>> v = ['a','e','i','o','u']
>>> len(a)
3
>>> sum([1 for x in a if x in v])
2
I do not follow why you use i in i in info together with count. If info is enumerable and enumerating has the same effect as accessing with a zero offset index (like you seem to do with count, you can rewrite your loop like:
lst = []
for infoi in info:
num = infoi["count"]
# print num
lst.append(num)
print sum(lst)
Now you can convert this to the following list comprehension:
sum([infoi["count"] for infoi in info])
Finally you do not need to materialize the comprehension to a list, sum can work on a generator:
sum(infoi["count"] for infoi in info)
This can be more efficient, since you will not construct a list first with all the values: sum will enumerate over all items and thus will result in constant memory usage.
I'm trying to write a Python function that counts the number of entries in a list that occur exactly once.
For example, given the list [17], this function would return 1. Or given [3,3,-22,1,-22,1,3,0], it would return 1.
** Restriction: I cannot import anything into my program.
The incorrect code that I've written so far: I'm going the double-loop route, but the index math is getting over-complicated.
def count_unique(x):
if len(x) == 1:
return 1
i = 0
j = 1
for i in range(len(x)):
for j in range(j,len(x)):
if x[i] == x[j]:
del x[j]
j+1
j = 0
return len(x)
Since you can't use collections.Counter or sorted/itertools.groupby apparently (one of which would usually be my go to solution, depending on whether the inputs are hashable or sortable), just simulate roughly the same behavior as a Counter, counting all elements and then counting the number of elements that appeared only once at the end:
def count_unique(x):
if len(x) <= 1:
return len(x)
counts = {}
for val in x:
counts[val] = counts.get(val, 0) + 1
return sum(1 for count in counts.values() if count == 1)
lst = [3,3,-22,1,-22,1,3,0]
len(filter(lambda z : z[0] == 1,
map(lambda x : (len(filter(lambda y : y == x, lst)), x), lst)))
sorry :)
Your solution doesn't work because you are doing something weird. Deleting things from a list while iterating through it, j+1 makes no sense etc. Try adding elements that are found to be unique to a new list and then counting the number of things in it. Then figure out what my solution does.
Here is the O(n) solution btw:
lst = [3,3,-22,1,-22,1,3,0,37]
cnts = {}
for n in lst:
if n in cnts:
cnts[n] = cnts[n] + 1
else:
cnts[n] = 1
count = 0
for k, v in cnts.iteritems():
if v == 1:
count += 1
print count
A more simple and understandable solution:
l = [3, 3, -22, 1, -22, 1, 3, 0]
counter = 0
for el in l:
if l.count(el) == 1:
counter += 1
It's pretty simple. You iterate over the items of the list. Then you look if the element is exactly one time in the list and then you add +1. You can improve the code (make liste comprehensions, use lambda expressions and so on), but this is the idea behind it all and the most understandable, imo.
you are making this overly complicated. try using a dictionary where the key is the element in your list. that way if it exists it will be unique
to add to this. it is probably the best method when looking at complexity. an in lookup on a dictionary is considered O(1), the for loop is O(n) so total your time complexity is O(n) which is desirable... using count() on a list element does a search on the whole list for every element which is basically O(n^2)... thats bad
from collections import defaultdict
count_hash_table = defaultdict(int) # i am making a regular dictionary but its data type is an integer
elements = [3,3,-22,1,-22,1,3,0]
for element in elements:
count_hash_table[element] += 1 # here i am using that default datatype to count + 1 for each type
print sum(c for c in count_hash_table.values() if c == 1):
There is method on lists called count.... from this you can go further i guess.
for example:
for el in l:
if l.count(el) > 1:
continue
else:
print("found {0}".format(el))