Finding missing elements in a List - python

Hello I have a List with a lot of element in it. These are numbers and ordered but some numbers are missing.
Example: L =[1,2,3,4,6,7,10]
Missing: M = [5,8,9]
How can I find missing numbers in Python?

Take the difference between the sets:
set(range(min(L),max(L))) - set(L)
If you are really crunched for time and L is truly sorted, then
set(range(L[0], L[-1])) - set(L)

This function should do the trick
def missing_elements(L):
s, e = L[0], L[-1]
return sorted(set(range(s, e + 1)).difference(L))
miss = missing_elements(L)

Here you are:
L =[1,2,3,4,6,7,10]
M = [i for i in range(1, max(L)) if i not in L]
# If 0 shall be included replace range(1, max(L)) to range(max(L))

With a comprehension it would look like this:
L = [1,2,3,4,6,7,10]
M = [i for i in range(min(L), max(L)+1) if i not in L]
M
#[5,8,9]
And a fun one, just to add to the bunch:
[i for a, b in zip(L, L[1:]) for i in range(a + 1, b) if b - a > 1]

L =[1,2,3,4,6,7,10]
R = range(1, max(L) + 1)
> [1,2,3,4,5,6,7,8,9,10]
M = list(set(R) - set(L))
> [5,8,9]
Note that M will not necessarily be ordered, but can easily be sorted.

Related

How to judge if a string contains a given substring (have gap)

e.g.
a = 'abc123def'
b = 'abcdef'
I want a function which can judge whether b in a.
contains(a,b)=True
p.s. gap is also allowed in the represention of b, e.g.
b='abc_def'
but regular expressions are not allowed.
If what you want to do is to check whether b is a subsequence of a, you can write:
def contains(a, b):
n, m = len(a), len(b)
j = 0
for i in range(n):
if j < m and a[i] == b[j]:
j += 1
return j == m
Try using list comprehension:
def contains(main_string, sub_string):
return all([i in main_string for i in sub_string])
NOTE: 'all' is a builtin function which takes an iterable of booleans and returns try if all are True.
def new_contained(a,b):
boo = False
c = [c for c in a]
d = [i for i in b]
if len(c)<=len(d):
for i in c:
if i in d:
boo = True
return boo

Find number of pairs that add up to a specific number from two different lists?

a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
def sumOfTwo(a,b,v):
for i in range (len(a)):
val_needed = v - a[i]
for j in range (len(b)):
if b[j] == val_needed:
x = b[j]
y = a[i]
print(x,y)
sumOfTwo(a,b,v=70)
Output: 5 65
What if more pairs are possible from the given lists in the problem, how do I do that?
Help.
What are more ways to achieve this?
If you just want to print matched values, you just have to indent the print statement to be inside theif, as stated below. Also, you should use a more pythonic approach to for loops and also for variable assignments.
a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
def sumOfTwo(a,b,v):
for i in a:
val_needed = v - i
for j in b:
if j == val_needed:
x, y = j, i
print(x,y)
sumOfTwo(a,b,v=70)
Using a list comprehension:
a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
c = [(x, y)
for x in a
for y in b
if x + y == 70]
print(c)
This yields
[(1, 69), (3, 67), (5, 65)]

Comparing elements in two lists in python

I have a function that compares the elements of two lists and returns the difference between them. I have two versions of it. The first one works but not the second one. What is wrong with the second function? The inputs a and b are two lists of same length.
def compareLists(a, b):
A = sum([1 if i > j else 0 for i, j in zip(a, b)])
B = sum([1 if j > i else 0 for i, j in zip(a, b)])
return (A, B)
def compareLists(a, b):
A = sum([1 for i in range(0, len(a)) if a[i] > b[i] else 0])
B = sum([1 for i in range(0, len(a)) if b[i] > a[i] else 0])
return (A, B)
Eg input and output: a = [1, 2, 3,4]; b = [0, -2, 5, 6]; output = (2, 2)
You don't need the ternary operator (if-else) in the second code since using the if expression in a list comprehension is how the output can be filtered:
A = sum([1 for i in range(0, len(a)) if a[i] > b[i]])
B = sum([1 for i in range(0, len(a)) if b[i] > a[i]])
Adding else as you do in your second code makes the syntax invalid.
For completeness, as #wim noted in the comment, the use of the ternary operator is unnecessary in your first code either because Boolean values in Python are simply integers of 1 and 0, so you can output the Boolean values returned by the comparison operators directly instead:
A = sum([i > j for i, j in zip(a, b)])
B = sum([j > i for i, j in zip(a, b)])

Subtraction between two nested lists of strings in Python

I am trying to follow the used structure in this question for nested lists but I'm confused and don't know how to figure it out. Suppose that to subtract the two lists a = ['5', '35.1', 'FFD'] and b = ['8.5', '11.3', 'AMM'], the following code is used for reaching to equation c = b - a:
diffs = []
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
>>> print(diffs)
['3.5', '-23.8', 'AMM-FFD']
My question is, how do I get C = B - A by considering the following structure:
A = [['X1','X2'],['52.3','119.4'],['45.1','111']]
B = [['Y1','Y2'],['66.9','65'],['99','115.5']]
C = [['Y1-X1','Y2-X2'],['14.6','-54.4'],['53.9','4.5']]
and how do I the first and second elements of each internal list, something like:
Array 1 = ['Y1-X1', '14.6', '53.9']
Array 2 = ['Y2-X2', '-54.4', '4.5']
I appreciate any kind of help.
Well, if it's guaranteed that the lists will always be 2 levels nested, you can simply add one more loop:
diffs_lists = []
for i, j in zip(a, b):
diffs = []
for k, l in zip(i, j):
try:
diffs.append(str(float(k) - float(l)))
except ValueError:
diffs.append('-'.join([k, l]))
diffs_lists.append(diffs)
To separate the result in two as you asked, simply use zip:
zip(*diffs_lists)
You just need another level of looping:
res = []
for a, b in zip(A, B):
diffs = []
res.append(diffs)
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
print(res)
#[['Y1-X1', 'Y2-X2'], ['14.600000000000009', '-54.400000000000006'], ['53.9', '4.5']]
print(list(zip(*res)))
#[('Y1-X1', '14.600000000000009', '53.9'), ('Y2-X2', '-54.400000000000006', '4.5')]
diffs=[]
for sub_b, sub_a in zip(b, a):
curr = []
for atom_b, atom_a in zip(sub_b, sub_a):
try:
curr.append(float(atom_b) - float(atom_a))
except ValueError:
curr.append('-'.join([atom_b, atom_a]))
diffs.append(curr)
ans1, ans2 = zip(*diffs)
The zip function can also be used to unzip iterables.
Suppose you have a list_diffs function, that is basically the code you provided:
list_diffs(a, b):
diffs = []
for i, j in zip(a, b):
try:
diffs.append(str(float(j) - float(i)))
except ValueError:
diffs.append('-'.join([j, i]))
return diffs
Then, the C you want is just a list whose elements are diffs between elements of A and elements of B. So the following gives you C:
C = []
for i in range(len(A)):
C.append(list_diffs(A[i], B[i]))
To get the lists of the first and of the second elements:
array1 = [c[0] for c in C]
array2 = [c[1] for c in C]
In case you need this to work with arbitrary amount of nesting you could use recursion:
def subtract(x, y):
diffs = []
for a, b in zip(x, y):
try:
if isinstance(a, list):
diffs.append(subtract(a, b))
else:
diffs.append(str(float(b) - float(a)))
except ValueError:
diffs.append('-'.join([b, a]))
return diffs
As others have pointed out zip can be used for unzipping:
res = subtract(A, B)
t1, t2 = zip(*res)
print(t1)
print(t2)
Output:
('Y1-X1', '14.6', '53.9')
('Y2-X2', '-54.4', '4.5')
i try it with a recursive method
A = [['X1','X2'],['52.3','119.4'],['45.1','111']]
B = [['Y1','Y2'],['66.9','65'],['99','115.5']]
C = [['Y1-X1','Y2-X2'],['14.6','-54.4'],['53.9','4.5']]
Array_a,Array_b = [[] for __ in range(2)]
def diff(B,A):
_a = 0
for b,a in zip(B,A):
if isinstance(b,list):
diff(b,a)
else:
try:
Array_b.append(float(b)-float(a)) if _a else Array_a.append(float(b)-float(a))
_a = True
except (ValueError,TypeError) as e:
Array_b.append("{0}-{1}".format(b,a)) if _a else Array_a.append("{0}-{1}".format(b,a))
_a = True
return (Array_a,Array_b)
print (diff(B,A))
>>>(['Y1-X1', 14.600000000000009, 53.9], ['Y2-X2', -54.400000000000006, 4.5])

How to find a missing number from a list?

How do I find the missing number from a sorted list the pythonic way?
a=[1,2,3,4,5,7,8,9,10]
I have come across this post but is there a more and efficient way to do this?
>>> a=[1,2,3,4,5,7,8,9,10]
>>> sum(xrange(a[0],a[-1]+1)) - sum(a)
6
alternatively (using the sum of AP series formula)
>>> a[-1]*(a[-1] + a[0]) / 2 - sum(a)
6
For generic cases when multiple numbers may be missing, you can formulate an O(n) approach.
>>> a=[1,2,3,4,7,8,10]
>>> from itertools import imap, chain
>>> from operator import sub
>>> print list(chain.from_iterable((a[i] + d for d in xrange(1, diff))
for i, diff in enumerate(imap(sub, a[1:], a))
if diff > 1))
[5, 6, 9]
This should work:
a = [1, 3, 4, 5, 7, 8, 9, 10]
b = [x for x in range(a[0], a[-1] + 1)]
a = set(a)
print(list(a ^ set(b)))
>>> [2, 6]
1 + 2 + 3 + ... + (n - 1) + n = (n) * (n + 1)/2
so the missing number is:
(a[-1] * (a[-1] + 1))/2 - sum(a)
set(range(a[len(a)-1])[1:]) - set(a)
Take the set of all numbers minus the set of given.
And another itertools way:
from itertools import count, izip
a=[1,2,3,4,5,7,8,9,10]
nums = (b for a, b in izip(a, count(a[0])) if a != b)
next(nums, None)
# 6
This will handle the cases when the first or last number is missing.
>>> a=[1,2,3,4,5,7,8,9,10]
>>> n = len(a) + 1
>>> (n*(n+1)/2) - sum(a)
6
If many missing numbers in list:
>>> a=[1,2,3,4,5,7,8,10]
>>> [(e1+1) for e1,e2 in zip(a, a[1:]) if e2-e1 != 1]
[6, 9]
def find(arr):
for x in range(0,len(arr) -1):
if arr[x+1] - arr[x] != 1:
print arr[x] + 1
Simple solution for the above problem, it also finds multiple missing elements.
a = [1,2,3,4,5,8,9,10]
missing_element = []
for i in range(a[0], a[-1]+1):
if i not in a:
missing_element.append(i)
print missing_element
o/p:
[6,7]
Here is the simple logic for finding mising numbers in list.
l=[-10,-5,2,4,5,9,20]
s=l[0]
e=l[-1]
x=sorted(range(s,e+1))
l_1=[]
for i in x:
if i not in l:
l_1.append(i)
print(l_1)
def findAllMissingNumbers(a):
b = sorted(a)
return list(set(range(b[0], b[-1])) - set(b))
L=[-5,1,2,3,4,5,7,8,9,10,13,55]
missing=[]
for i in range(L[0],L[-1]):
if i not in L:
missing.append(i)
print(missing)
A simple list comprehension approach that will work with multiple (non-consecutive) missing numbers.
def find_missing(lst):
"""Create list of integers missing from lst."""
return [lst[x] + 1 for x in range(len(lst) - 1)
if lst[x] + 1 != lst[x + 1]]
There is a perfectly working solution by #Abhiji. I would like to extent his answer by the option to define a granularity value. This might be necessary if the list should be checked for a missing value > 1:
from itertools import imap, chain
from operator import sub
granularity = 3600
data = [3600, 10800, 14400]
print list(
chain.from_iterable(
(data[i] + d for d in xrange(1, diff) if d % granularity == 0)
for i, diff in enumerate(imap(sub, data[1:], data))
if diff > granularity
)
)
The code above would produce the following output: [7200].
As this code snipped uses a lot of nested functions, I'd further like to provide a quick back reference, that helped me to understand the code:
Python enumerate()
Python imap()
Python chain.from_iterable()
Less efficient for very large lists, but here's my version for the Sum formula:
def missing_number_sum(arr):
return int((arr[-1]+1) * arr[-1]/2) - sum(arr)
If the range is known and the list is given, the below approach will work.
a=[1,2,3,4,5,7,8,9,10]
missingValues = [i for i in range(1, 10+1) if i not in a]
print(missingValues)
# o/p: [6]
set(range(1,a[-1])) | set(a)
Compute the union of two sets.
I used index position.
this way i compare index and value.
a=[0,1,2,3,4,5,7,8,9,10]
for i in a:
print i==a.index(i)

Categories

Resources