how to find multiple non-repeating numbers in python? - python

I have a below method that finds the non-repeating elements in a list:
def dupes(a):
s = {}
for ele in a:
if ele not in s:
s[ele] = 1
else:
s[ele] += 1
for x in s:
if s[x] == 1:
return 'this is the only non-repeating element value is :', s[x], 'and the key is :', x
return
l = [4, 7, 4, 5, 7, 6, 5, 6, 10]
cd = dupes(l)
print("This is dupes: ", cd)
The code runs successfully and below is the output:
This is dupes: ('this is the only non-repeating element value is :', 1, 'and the key is :', 10)
But when I am trying to add more than one non-repeating elements in the list, the output doesn't change. For example, if I add 11 at the end of the list the output still remains the same as above..
Any idea?

Actually when you return at the 10th line, the function ends. This is in case you don't understand the list comprehension yet, as many have given you the solution with that technique. I will just give you a simple solution where it will return a list of non-repeating numbers.
def dupes(a):
s = {}
non_dupes = []
for ele in a:
if ele not in s:
s[ele] = 1
else:
s[ele] += 1
for x in s:
if s[x] == 1:
non_dupes.append(x)
return non_dupes
l = [4, 7, 4, 5, 7, 6, 5, 6, 10, 11]
cd = dupes(l)
print("This is dupes: ", cd)

def dupes(a):
s = {}
for ele in a:
if ele not in s:
s[ele] = 1
else:
s[ele] += 1
count = 0
keys = []
for x in s:
if s[x] == 1:
count += 1
keys.append(x)
return 'this is the only non-repeating element value is :', count, 'and the key is :', keys
That would be fine.

You can get all keys whose value is 1 using a list comprehension.
nondupes = [k for (k,v) in s.items() if v==1]
return 'Non-repeating elements: ' + str(nondupes)
Also, you could replace all your counting code with a collections.Counter:
s = Counter(a)

You can easely solve this in one line of python code, using the count() function:
l = [4, 7, 4, 5, 7, 6, 5, 6, 10 ,11]
only_one_time = [e for e in l if l.count(e) < 2]
print(only_one_time)

The given code returns the first non-repeating element it encounters.
For example,
if the input list is l = [12, 11, 4, 7, 4, 5, 7, 6, 5, 6, 10],
the output would be This is dupes: ('this is the only non-repeating element value is :', 1, 'and the key is :', 12).

You can succinctly achieve the above with Counter:
from collections import Counter
l = [4, 7, 4, 5, 7, 6, 5, 6, 10]
c = Counter(l)
dupes = list(key for key in c if c[key] > 1)
print("This is dupes: ", dupes)
Output:
This is dupes: [4, 7, 5, 6]
The issue that you are encountering is that you are returning prematurely from your function with a string containing the first duplicate. The rest of the duplicates are lost.
You already have the list of duplicates, let's return just the data so we can separate the calculation of results from the display of results.
return list(e for e in s if s[e] > 1)

Related

Getting most common element from list in Python

I was able to use this piece of code to find the most common value if there was only one, however, it wouldn't work if there were multiple. I want it so that if there are multiple, it would just return None.
numbers = [5, 3, 5, 3, 2, 6, 7]
my_dict = {}
for i in numbers:
if i in my_dict:
my_dict[i] += 1
else:
my_dict[i] = 1
print(max(my_dict, key=my_dict.get))
You can use the key to get the number of occurrences of the highest value.
numbers = [5, 3, 5, 3, 2, 6, 7]
my_dict = {}
for i in numbers:
if i in my_dict:
my_dict[i] += 1
else:
my_dict[i] = 1
#print(max(my_dict, key=my_dict.get))
mx=max(my_dict, key=my_dict.get)
mn=my_dict[mx]
if mn == 1:
print(mx, ' is the highest')
else:
print('there are ',mn, ' of ',mx)
Output
there are 2 of 5
Use a library function to sort the numbers:
s = sorted(numbers)
Check if the last two numbers are the same (then you have more than one max):
one_max = s[-1] if (len(s)==1 or s[-1]!=s[-2]) else None
#ada7ke This will print None if there is more than 1 highest number. Otherwise it will print the number
numbers = [5, 7, 5, 3, 2, 6, 7]
highest = max(numbers)
indices = [i for i, x in enumerate(numbers) if x == highest]
frequency = numbers.count(highest)
if frequency > 1:
print(None)
else:
print(highest)

How would I fix this function?

Hey this is my first question so I hope I'm doing it right.
I'm trying to write a function that given a list of integers and N as the maximum occurrence, would then return a list with any integer above the maximum occurrence deleted. For example if I input:
[20,37,20,21] #list of integers and 1 #maximum occurrence.
Then as output I would get:
[20,37,21] because the number 20 appears twice and the maximum occurrence is 1, so it is deleted from the list. Here's another example:
Input: [1,1,3,3,7,2,2,2,2], 3
Output: [1,1,3,3,7,2,2,2]
Here's what I wrote so far, how would I be able to optimize it? I keep on getting a timeout error. Thank you very much in advance.
def delete_nth(order,n):
order = Counter(order)
for i in order:
if order[i] > n:
while order[i] > n:
order[i] - 1
return order
print(delete_nth([20,37,20,21], 1))
You can remove building the Counter at the beginning - and just have temporary dictionary as counter:
def delete_nth(order,n):
out, counter = [], {}
for v in order:
counter.setdefault(v, 0)
if counter[v] < n:
out.append(v)
counter[v] += 1
return out
print(delete_nth([20,37,20,21], 1))
Prints:
[20, 37, 21]
You wrote:
while order[i] > n:
order[i] - 1
That second line should presumably be order[i] -= 1, or any code that enters the loop will never leave it.
You could use a predicate with a default argument collections.defaultdict to retain state as your list of numbers is being filtered.
def delete_nth(numbers, n):
from collections import defaultdict
def predicate(number, seen=defaultdict(int)):
seen[number] += 1
return seen[number] <= n
return list(filter(predicate, numbers))
print(delete_nth([1, 1, 3, 3, 7, 2, 2, 2, 2], 3))
Output:
[1, 1, 3, 3, 7, 2, 2, 2]
>>>
I've renamed variables to something that had more meaning for me:
This version, though very short and fairly efficient, will output identical values adjacently:
from collections import Counter
def delete_nth(order, n):
counters = Counter(order)
output = []
for value in counters:
cnt = min(counters[value], n)
output.extend([value] * cnt)
return output
print(delete_nth([1,1,2,3,3,2,7,2,2,2,2], 3))
print(delete_nth([20,37,20,21], 1))
Prints:
[1, 1, 2, 2, 2, 3, 3, 7]
[20, 37, 21]
This version will maintain original order, but run a bit more slowly:
from collections import Counter
def delete_nth(order, n):
counters = Counter(order)
for value in counters:
counters[value] = min(counters[value], n)
output = []
for value in order:
if counters[value]:
output.append(value)
counters[value] -= 1
return output
print(delete_nth([1,1,2,3,3,2,7,2,2,2,2], 3))
print(delete_nth([20,37,20,21], 1))
Prints:
[1, 1, 2, 3, 3, 2, 7, 2]
[20, 37, 21]

Conditional checking between two int objects

I am iterating in a for loop, constructing a list, whilst comparing the last number of that list with another number.
I would like my code to see if the last item of the list is smaller than the item it is being compared to, and if it is, to add it to the end of its list and then to continue.
if the last item of the list is larger, i would like to pop off the last item of the list. i would then like to subject it to the same conditionals.
here is my code, it is not working, it wont re check the conditionals after popping off the last item of the list.
if tempList:
lastNum=tempList[-1]
#############################################
if element < lastNum:
incList.append(tempList)
tempList.pop()
lastNum=tempList[-1]
#############################################
elif lastNum < element:
tempList.append(element)
continue
You can bundle this into a function:
def append_if_lower_else_pop_end_from_list_until_lower(l, num):
"""Add num to l if l[-1] < num, else pop() from l until"""
while l and l[-1] > num:
l.pop()
l.append(num)
# this is not strictly needed - lists are mutable so you are mutating it
# returning it would only make sense for chaining off it with other methods
return l
k = [3,5,7,9,11,13]
print(k)
append_if_lower_else_pop_end_from_list_until_lower(k, 10)
print(k)
append_if_lower_else_pop_end_from_list_until_lower(k, 6)
print(k)
append_if_lower_else_pop_end_from_list_until_lower(k, 10)
print(k)
append_if_lower_else_pop_end_from_list_until_lower(k, 10)
print(k)
append_if_lower_else_pop_end_from_list_until_lower(k, -10)
print(k)
Output:
[3, 5, 7, 9, 11, 13] # start
[3, 5, 7, 9, 10] # after adding 10
[3, 5, 6] # after addding 6
[3, 5, 6, 10] # after adding 10
[3, 5, 6, 10, 10] # after adding 10 again
[-10] # after adding -10
Why return the list as well: example for chaining:
k = [3,5,17,9,11,13]
append_if_lower_else_pop_end_from_list_until_lower(k, 10).sort()
print(k)
Output:
[3, 5, 9, 10, 17]
Try this out:
yourlist = [3,1,4]
n = 1
resultlist = yourlist[:-1] if yourlist[-1]>=n else yourlist+[n]
print(resultlist)
n = 5
resultlist = yourlist[:-1] if yourlist[-1]>=n else yourlist+[n]
print(resultlist)
Output:
[3,1]
[3,1,4,5]

How to efficiently make a numbered list in python Class-list

How to make the following code more compact and efficient.
Here, the code was to find the position where certain numerical value resides in the list.
For example, given set of number
ListNo = [[100,2,5], [50,10], 4, 1, [6,6,500]]
The value of 100, 50 and 500 was in the position of 0,3 and 9, respectively.
The testing code was as follows
ListNo = [[100,2,5], [50,10], 4, 1, [6,6,500]]
NumberedList = ListNo
Const = 0
items = 0
for i, item in enumerate(ListNo):
MaxRange = len(item) if isinstance(item, list) else 1
for x in range(0, MaxRange):
if MaxRange > 1:
NumberedList[i][x] = Const
else:
NumberedList[i] = Const
Const = Const + 1
print(NumberedList)
[[0, 1, 2], [3, 4], 5, 6, [7, 8, 9]]
My question is, whether there is another option to make this code more compact and efficient.
You can use itertools.count:
from itertools import count
i = count()
print([[next(i) for _ in range(len(l))] if isinstance(l, list) else next(i) for l in ListNo])
This outputs:
[[0, 1, 2], [3, 4], 5, 6, [7, 8, 9]]
A recursive solution would be more elegant, and handle more cases:
def nested_list_ordinal_recurse(l, it):
if isinstance(l, list):
return [nested_list_ordinal_recurse(item, it) for item in l]
else:
return next(it)
def nested_list_ordinal(l, _it=None):
return nested_list_ordinal_recurse(l, itertools.count())
ListNo = [[100,2,5], [50,10], 4, 1, [6,6,500]];
count=-1
def counter(l=[]):
global count
if l:
return [counter() for i in l]
else:
count+=1
return count
print [counter(item) if isinstance(item, list) else counter() for item in ListNo ]
Without iter tools

Python: A program to find the LENGTH of the longest run in a given list?

Q: A run is a sequence of adjacent repeated values. Given a list, write a function to
determine the length of the longest run. For example, for the sequence [1, 2, 5, 5, 3, 1, 2, 4, 3, 2, 2, 2, 2, 3, 6, 5, 5, 6, 3, 1], the longest run is 4.
I am having trouble with this, I've written a code that finds the longest run consist of the number '2' but have yet to get the length of the run which is 4.
Here is my code so far (i've commented out a part that i was working on but don't pay attention to it):
# longestrun.py
# A function to determine the length of the longest run
# A run is a sequence of adjacent repeated values.
def longestrun(myList):
result = None
prev = None
size = 0
max_size = 0
for i in myList:
if i == prev:
size += 1
if size > max_size:
result = i
max_size = size
else:
size = 0
prev = i
return result
def main():
print("This program finds the length of the longest run within a given list.")
print("A run is a sequence of adjacent repeated values.")
myString = input("Please enter a list of objects (numbers, words, etc.) separated by
commas: ")
myList = myString.split(',')
longest_run = longestrun(myList)
print(">>>", longest_run, "<<<")
main()
Help please!!! :(((
You can do this in one line using itertools.groupby:
import itertools
max(sum(1 for _ in l) for n, l in itertools.groupby(lst))
This should work if you do not want to use itertools and imports.
a=[1, 2, 5, 5, 3, 1, 2, 4, 3, 2, 2, 2, 2, 3, 6, 5, 5, 6, 3, 1]
def longestrun(myList):
result = None
prev = None
size = 0
max_size = 0
for i in myList:
if i == prev:
print (i)
size += 1
if size > max_size:
print ('******* '+ str(max_size))
max_size = size
else:
size = 0
prev = i
print (max_size+1)
return max_size+1
longestrun(a)
Just another way of doing it:
def longestrun(myList):
sett = set()
size = 1
for ind, elm in enumerate(myList):
if ind > 0:
if elm == myList[ind - 1]:
size += 1
else:
sett.update([size])
size = 1
sett.update([size])
return max(sett)
myList = [1, 2, 5, 5, 3, 1, 2, 4, 3, 2, 2, 2, 2, 3, 6, 5, 5, 6, 3, 1]
print longestrun(myList)
def getSublists(L,n):
outL=[]
for i in range(0,len(L)-n+1):
outL.append(L[i:i+n])
return outL
def longestRun(L):
for n in range(len(L), 0, -1):
temp=getSublists(L,n)
for subL in temp:
if subL==sorted(subL):
return len(subL)
def longestrun(myList):
size = 1
max_size = 0
for i in range(len(myList)-1):
if myList[i+1] = myList[i]:
size += 1
else:
size = 1
if max_size<size:
max_size = size
return size
Remove the .split() from myList in main() and you're good to go with this.
As an update to David Robinson's answer, it is now (Python 3.4) possible to return 0 on an empty sequence (instead of raising ValueError):
import itertools
max((sum(1 for _ in l) for n, l in itertools.groupby(lst)), default=0)

Categories

Resources