How to count numbers less than a given number including duplicates - python

I have a task to count numbers less than a given number. I understand this for most cases except ones with duplicates. So for example a list [1,2,2,3,4] I want the out put of this to be a count of 2 since it not including the middle one
One way I’ve tried this target is the number is the given number to find the less than to
count=0
for i in list:
if i< target:
count=count+1
return count
I know if I put = it will count both twos how can I fix this with what I have now and it still being a list

I would first remove duplicates like this:
res = []
[res.append(x) for x in list if x not in res]
and then you could get the number of values in the list without duplicates with the len function: len(res) or check each value to make sure it meets criteria before counting like being less then a number:
count = 0
for i in res:
if i < target: count += 1
return count
Although it might be faster to create a list of numbers that are both not duplicates and meet the criteria, and then just take the length of that list:
res = []
[res.append(x) for x in list if x not in res and x < target]
return len(res)

Put all the list items into a set and then count the number of elements less than target:
>>> a_list = [1, 2, 2, 3, 4]
>>> target = 3
>>> sum(i < target for i in set(a_list))
2

You can just change list to a set. That is, loop through a set of the list. This way you will go through each unique element once. See the code below:
count = 0
for element in set(list):
if element < target:
count += 1
print(count)

You can simply use a list comprehension:
target = 3 # can be any other number
len([x for x in set(myList) if x < target])

Related

How do I find the number of ordered group possible as in a sublist from a super list in python?

Suppose I have a smaller list A = [1,2,3] and larger list B = [1,2,3,1,1,2,2,3,2,3].
B has no other elements except A's but elements order is not maintained.
I want to find how many times A appears in B preserving A's order. For this example A appears 3 times in B. I could solve this for two elements, like [1,2] comes 2 times in [1,1,2,2,1,1]. In other words, I want to find how many ordered group such A is possible from the larger list as B.
From what I understood, you want to count how many times all the elements of A are repeated in order in B, even if there are other elements inbetween.
If that's the case, you can use:
A = [1,2,3]
B = [1,1,1,1,1,1,1,1,1,2,3,1,1,2,2,3,2,3,3,3,3,3,3,3,3]
counters = [0 for _ in A] # initialize a list with the same number of values of A, but all at 0
for x in B: # for each element in B
for n in range(len(A)): # for all the indexes in A
if x == A[n]: # if the element in B is present in A
if n == 0 or (counters[n] < counters[n-1]):
# if n == 0, is the first element of A: we know it's a start of a possible match
# if the previous number in index is higher of the current number, means that we are looking for the match to continue
counters[n] += 1 # add 1 to the current number
break
print counters[-1] # the last number of the counters represent the times that you reached the end of a match
An efficient approach is to build a dict of queues of indices for each item in B, then cycle through items in A to look for the next item in the dict whose index is greater than the index of the last found item by keeping dequeueing until such an index is found or break the loop if any queue is exhausted, with each completed cycle incrementing the count by 1:
from collections import deque
index = {}
for i, n in enumerate(B):
index.setdefault(n, deque()).append(i)
count = 0
while True:
last = -1
try:
for n in A:
while True:
i = index[n].popleft()
if i > last:
last = i
break
except (IndexError, KeyError):
break
count += 1
count becomes:
3

Matching exact elements in a set where order doesn't matter

I'm new to python and I'm trying to match the exact elements between two sets, regardless of order. So if my 2 sets are:
reflist = [1],[2,3,4],[5,6]
qlist = [1,2,3,4],[6,5]
The number of matches should be 1, which is 5,6
I tried to write the following loop to match the elements in qlist against reflist, and count the number of matches:
i = 0
count = 0
for each in qlist:
while i < len(qlist):
if each.split(",").sort == reflist[i].split(",").sort:
count = count + 1
i = i + 1
print count
However, I keep getting count = 0, even if the order of 5 and 6 in qlist is 5,6. Would really appreciate any help with this!
If there are no duplicates in your "sets", convert your "sets" to a set of frozensets, and find the set intersection -
i = set(map(frozenset, reflist))
j = map(frozenset, qlist)
len(i.intersection(j))
1
This could do:
If you have no duplicates:
matches = [x for x in map(set, reflist) if x in map(set, qlist)]
If you have duplicates:
matches = [x for x in map(sorted, reflist) if x in map(sorted, qlist)]
You could always use collections.Counter() for this:
from collections import Counter
reflist = [[1],[2,3,4],[5,6]]
qlist = [[1,2,3,4],[6,5]]
result = [list(x.keys()) for x in [Counter(y) for y in reflist] if x in [Counter(y) for y in qlist]]
print(result)
Which Outputs:
[[5,6]]
Here is my one-liner, using frozensets and and:
len(set(map(frozenset, qlist)) and set(map(frozenset, reflist)))
I understand you are new to Python, hence I will answer your question using your own method, just for the sake of recording the basic straightforward answer for future reference.
First of all, your code shouldn't run at all. It must error out, because both each and reflist[i] are lists, and you are applying a string method of split(",") on them. Therefore you are getting the initial value of count = 0. You must check in the first place whether your code is even touching all the elements of qlist and reflist. This is not Code Review, hence I will leave it to you to run this and see the answer:
i = 0
count = 0
for each in qlist:
while i < len(qlist):
print i
print each
print reflist[i]
i = i + 1
Keep in mind: You don't have to iterate on index! You can just loop over the elements of iterables directly! This is the answer you are looking for:
match = [] # Optional, to see all the matching elements
count = 0
for q in qlist:
for r in reflist:
if set(q) == set(r):
print q, r
match.append(q)
count += 1
print match
print count, len(match)

Counting consecutive numbers in a list

I couldn't find a question that was similar enough to mine to where I could develop a satisfactory answer.
I'm pretty new to Python (3.4.3). I am trying to add elements to an output list using a for loop by comparing each element of an input list to the next element in it.
Here is my code so far:
random_list=[1,4,5,6,7,9,19,21,22,23,24]
def count_consec(random_list):
count=1
consec_list=[]
for i in listrand:
if listrand[i] == listrand[i+1]+1:
count+=1
else:
list.append(count)
return consec_list
Basically, I want to add to consec_list[] values that represent how the length of consecutive blocks of numbers in random_list[].
I expect my output in this case to look like this:
[1,4,1,1,4]
As in, there is one singular number, followed by 4 consecutive numbers, followed by one singular number, followed by one singular number, followed by 4 consecutive numbers.
I tried many different ways and I have gotten the function to build a list, but all the elements are 1s.
You could take an approach like this:
def countlist(random_list):
retlist = []
# Avoid IndexError for random_list[i+1]
for i in range(len(random_list) - 1):
# Check if the next number is consecutive
if random_list[i] + 1 == random_list[i+1]:
count += 1
else:
# If it is not append the count and restart counting
retlist.append(count)
count = 1
# Since we stopped the loop one early append the last count
retlist.append(count)
return retlist
There are a few problems with your code, among others undefined variables, or using an element i from the list as the index of that element, but also you will get an index error for the last element, and you never add the last count to the result list.
Instead, I'd suggest using the zip(lst, lst[1:]) recipe for iterating pairs of elements from the list, and using consec[-1] to access and modify the counts already in the list.
def count_consec(lst):
consec = [1]
for x, y in zip(lst, lst[1:]):
if x == y - 1:
consec[-1] += 1
else:
consec.append(1)
return consec
random_list=[1,4,5,6,7,9,19,21,22,23,24]
print(count_consec(random_list))
# [1, 4, 1, 1, 4]
Alternatively, you could subtract the index from each element. This way, successive consecutive elements will end up being the same element. Now, you can just use itertools.groupby to group and count those elements.
>>> random_list=[1,4,5,6,7,9,19,21,22,23,24]
>>> [e-i for i, e in enumerate(random_list)]
[1, 3, 3, 3, 3, 4, 13, 14, 14, 14, 14]
>>> [sum(1 for _ in g) for _, g in itertools.groupby(_)]
[1, 4, 1, 1, 4]
The following code fixes it up. You were iterating over the elements of the list itself instead of the counter you were referencing.
random_list=[1,4,5,6,7,9,19,21,22,23,24]
def count_consec(listrand):
count=1
consec_list=[]
for i in range(len(listrand[:-1])):
if listrand[i]+1 == listrand[i+1]:
count+=1
else:
consec_list.append(count)
count=1
# Account for the last iteration
consec_list.append(count)
return consec_list
print(count_consec(random_list))
Returns this:
[1, 4, 1, 1, 4]
Here's my version
Say you had a list of numbers, which you want to loop through and count the consecutive streaks:
list_of_nums = [4,5,7,8,2,1,3,5,7,6,8,9,9,9,2,2]
You could do something like this:
streak_count = []
counter = 1
for i in range(len(list_of_nums)):
if i != (len(list_of_nums) - 1):
diff = list_of_nums[i+1] - list_of_nums[i]
if diff == 1:
counter += 1
else:
streak_count.append(counter)
counter = 1
else:
streak_count.append(counter)

Negative number finder in index and occuring

Write a func/on first_neg that takes a (possibly empty) list of
numbers as input parameter, finds the first occurrence of a
nega/ve number, and returns the index (i.e. the posi/on in the
list) of that number. If the list contains no nega/ve numbers or it
is empty, the program should return None. Use while loop (and
not for loop) and your while loop should stop looping once the
first nega/ve number is found.
This is the question my teacher asked me any ideas this what i did:
def first_neg(list):
count = 0
for number in list:
if number < 0:
count += 1
return count
Dosent seem to work properly i just joined 1st post hope can get some help
x = [1,2,3,-5]
def first_neg(list):
count = 0
for number in list:
count += 1 #moved it outside of the if
if number < 0:
return count
print(first_neg(x)) #prints 4
You want to increment count not when you've found the answer but everytime the forloops loops. Note that this method returns 4 which is the fourth item in the list, not the index, Index of the list starts from 0 so to access it would be 3. Take our list x = [1,2,3,-5], -5 is in the fourth slot of the list, but to access it we have to call x[3] since lists starts at 0 indexing.
If you want to return the index of the list where the first negative number is found try this:
x = [1,2,3,-5]
def first_neg(list):
for count, number in enumerate(list):
if number < 0:
return count
print(first_neg(x)) # prints 3
This is because enumerate creates a "pairing" of the item in the list and it's the current count. Enumerate just counts from 0 everytime it gets an item out of the list.
Also as a side note ( I didn't change it in my answer since I wanted you to understand what's going on ). Don't name your variables keywords like list, tuple, int, str... Just a bad idea and habit, it works as you can see but it can cause issues.
Return the index immediately once you encounter the negative element. Increment the index otherwise:
def first_neg(lst):
count = 0
while count < len(lst):
if lst[count] < 0:
return count
count = count + 1
return None
Note : Better if you use enumerate() rather than using extra count variable. The code you mentioned is not written in pythonic way.
You may try this as well:
def first_neg(lst):
res = [i for i,x in enumerate(lst) if x<0]
return None if res == [] else res[0]
The code above can be improved using generators as suggested by #Chris_Rands.

Iterate over lists with a particular sum

I would like to iterate over all lists of length n whose elements sum to 2. How can you do this efficiently? Here is a very inefficient method for n = 10. Ultimately I would like to do this for `n > 25'.
n = 10
for L in itertools.product([-1,1], repeat = n):
if (sum(L) == 2):
print L #Do something with L
you only can have a solution of 2 if you have 2 more +1 than -1 so for n==24
a_solution = [-1,]*11 + [1,]*13
now you can just use itertools.permutations to get every permutation of this
for L in itertools.permutations(a_solution): print L
it would probably be faster to use itertools.combinations to eliminate duplicates
for indices in itertools.combinations(range(24),11):
a = numpy.ones(24)
a[list(indices)] = -1
print a
note for you to get 2 the list must be an even length
One way is to stop your product recursion whenever the remaining elements can't make up the target sum.
Specifically, this method would take your itertools.product(...,repeat) apart into a recursive generator, which updates the target sum based on the value of the current list element, and checks to see if the resulting target is achievable before recursing further:
def generate_lists(target, n):
if(n <= 0):
yield []
return
if(target > n or target < -n):
return
for element in [-1,1]:
for list in generate_lists(target-element, n-1):
yield list+[element]

Categories