Count the element of array inside a list - python

I have arrays inside list and I want to count the number of element in an array from two different lists instead of counting the list items.
code
import numpy as np
def count_total(a,b):
#count the total number of element for two arrays in different list
x,y=len(a),len(b)
result=[]
for a1 in a:
for b2 in b:
result.append(x+y)
return result
a=[np.array([2,2,1,2]),np.array([1,3])]
b=[np.array([4,2,1])]
c=[np.array([1,2]),np.array([4,3])]
print(count_total(a,b))
print(count_total(a,c))
print(count_total(b,c))
Actual output
[3, 3]
[4, 4, 4, 4]
[3, 3]
Desired output
[7,5]
[6,6,4,4]
[5,5]
Can anyone help ?

It looks to me from you examples you want all the possible ways to sum the length of the arrays. This can be achieved with itertools.product. Here is my code:
from itertools import product
def count_total(a,b):
return [sum(map(len, i)) for i in product(a, b)]
The product return all possible arrangements for one element each from a and b. Then for each arrangement, we take the len of the parts in the arrangement from each list, then add them together with sum.

Bug is in line 4, x and y are assigned list lengths rather than array lengths.
Replace the line 4-8
x,y=len(a),len(b)
result=[]
for a1 in a:
for b2 in b:
result.append(x+y)
with
y= lambda x:len(x)
result=[]
for a1 in a:
for b1 in b:
result.append(y(a1) + y(b1))

Related

Given multiple lists, how to find the values between neighboring lists?

I have multiple lists of increasing numbers. The elements in each list are strictly greater than those in its previous neighbor. i.e. [1,2,3], [6,7,8], [10,11,12].
How to find the numbers between neighboring lists? In this case, the results would be [4,5], [9].
If there are only two lists, I can use something like
a = [1,2,3]
b = [4,5,6]
result = list(range(a[-1]+1,b[0]))
but I can't think of a simple and fast way to construct a loop to do this if I have more than two lists.
Assuming that the lists are sorted and that the elements in each list are strictly increasing you can use a loop to iterate over the indices of the lists and uses the range() function to generate a list of numbers between the last element of the current list and the first element of the next list. The results are appended to the results array:
def find_gaps(lists):
gaps = []
for i in range(len(lists) - 1):
gap = list(range(lists[i][-1] + 1, lists[i + 1][0]))
gaps.append(gap)
return gaps
lists = [[1, 2, 3], [6, 7, 8], [10, 11, 12]]
print(find_gaps(lists))
The resulting list of arrays will contain the numbers between neighboring lists: [[4, 5], [9]]. The complexity of the find_gaps() function is O(n), where n is the number of lists.
You can try the following:
a,b,c=[1,2,3], [6,7,8], [10,11,12]
c=[a,b,c]
result=[]
for i in range(len(c)-1):
result.append(list(range(c[i][-1]+1,c[i+1][0])))
print(result)

remove pairs of equal elements from two lists in sympy

I am quite new to Sympy (running with Python 3).
Given two lists of integers, in general not of equal lengths and whose elements might repeat, I need to eliminate all pairs of equal elements between the two lists.
For example, given
List_a=[1, 2, 3, 4, 4], List_b=[0, 2, 2, 4]
I shall eliminate the pairs (2,2) and (4,4) and output
List_ar=[1,3,4], List_br=[0,2]
If the two lists are equal I shall get two empty lists as output.
I have been trying to compare the lists element by element ( "for" and "while" loops) and when found equal to delete the pair from both lists. Upon that to repeat the procedure on the reduced lists till no deletion is made.
But lacking of a "goto" control I do not know how to handle the variable length lists.
Thanks for helping.
I you convert them to multiset you can compare the counts of common keys:
>>> from sympy.utilities.iterables import multiset
>>> ma = multiset(lista)
>>> mb = multiset(listb)
>>> for k in set(ma) & set(mb):
... n = min(ma[k],mb[k])
... ma[k] -= n
... mb[k] -= n
...
>>> lista = [i for k in ma for i in [k]*ma[k]]
>>> listb = [i for k in mb for i in [k]*mb[k]]
You could also treat this like a merge sort but the above is direct.
A general Python solution:
def g(a, b):
def ensure2(xs):
ys = [list(x) for x in xs]
if ys == []:
return [[], []]
else:
return ys
n = min(len(a), len(b))
c, d = ensure2(
zip(*
filter(lambda x: x[0] != x[1],
zip(a, b))))
return c + a[n:], d + b[n:]
a = [1,2,3,4,4]
b = [0,2,2,4]
c = [0,2,2,4]
d = []
# two different lists
ar, br = g(a, b)
print(ar) # [1, 3, 4]
print(br) # [0, 2]
# two identical lists
br, cr = g(b, c)
print(br) # []
print(cr) # []
# one empty list
ar, dr = g(a, d)
print(ar) # [1, 2, 3, 4, 4]
print(dr) # []
Use zip() to create the pairs
Use filter() to remove pairs with equal elements
Use zip(*...) to split the remaining pairs back to two lists
Use ensure2() to guard against empty lists
Use + list[n:] to append excessive elements back to the originally longer list

using loops to create a new array that gets its values from a different array, starting on the second element and multiplying by the previous element

I am trying to make a function that creates an array from the functions original array, that starts on the second element and multiplies by the previous element.
Example
input: [2,3,4,5]
output: [6,12,20]
I am trying to use a loop to get this done and here is my code so far
def funct(array1):
newarray = []
for x in array1[1:]:
newarray.append(x*array1)
return newarray
I am at a loss as I am just learning python, and i've tried various other options but with no success. Any help is appreciated
try
A = [2, 3, 4, 5]
output = [a*b for a, b in zip(A[1:], A[:-1])]
You can use a list comprehension like so:
inp = [2,3,4,5]
out = [j * inp[i-1] for i,j in enumerate(inp) if i != 0]
Output:
[6,12,20]

How to pick the smallest value in a list when an iterative process is applied to the list

I need to find the smallest value in a series of lists. I understand the code for the smallest value in just one list:
>>> x = [1, 2, 3, 4, 5]
>>> print (min(x))
1
Simple enough. However, I would like to know if there is a way to write code that finds the smallest value for each list I have without stopping and adjusting the code (whether by an iterative process or some other means). Any help would be greatly appreciated. Thanks in advance!
First, make a list of lists out of your separate lists. For example, if you have lists A, B and C, the list of lists would be [A,B,C].
Now, to get a list of all the minimum values for each list in a list of lists lst:
[min(x) for x in lst]
To get the global minimum:
min(x for sublist in lst for x in sublist)
Demo:
>>> lst
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [min(x) for x in lst]
[1, 4, 7]
>>> min(x for sublist in lst for x in sublist)
1
Edit in reaction to OP's comment:
I just want the minimum value for each list. I don't need to compile all of the minimum values together into a new list
If you just want to print the minimum values for each list A, B, C, ... , you can do:
for lst in (A,B,C): # put as many lists as you like into the parentheses
print(min(lst))
Edit in reaction to
I am only accessing one list (in this case, the values are well depths) at a time. [..] What I would like to know is how to write a code that finds the smallest value in a list given that the iterator essentially changes the values in said list.
Just print(min(lst)) each time lst has changed.
Assuming you've got a list of lists, this should do it:
minimums = [min(l) for l in lists]

How to find elements existing in two lists but with different indexes

I have two lists of the same length which contains a variety of different elements. I'm trying to compare them to find the number of elements which exist in both lists, but have different indexes.
Here are some example inputs/outputs to demonstrate what I mean:
>>> compare([1, 2, 3, 4], [4, 3, 2, 1])
4
>>> compare([1, 2, 3], [1, 2, 3])
0
# Each item in the first list has the same index in the other
>>> compare([1, 2, 4, 4], [1, 4, 4, 2])
2
# The 3rd '4' in both lists don't count, since they have the same indexes
>>> compare([1, 2, 3, 3], [5, 3, 5, 5])
1
# Duplicates don't count
The lists are always the same size.
This is the algorithm I have so far:
def compare(list1, list2):
# Eliminate any direct matches
list1 = [a for (a, b) in zip(list1, list2) if a != b]
list2 = [b for (a, b) in zip(list1, list2) if a != b]
out = 0
for possible in list1:
if possible in list2:
index = list2.index(possible)
del list2[index]
out += 1
return out
Is there a more concise and eloquent way to do the same thing?
This python function does hold for the examples you provided:
def compare(list1, list2):
D = {e:i for i, e in enumerate(list1)}
return len(set(e for i, e in enumerate(list2) if D.get(e) not in (None, i)))
since duplicates don't count, you can use sets to find only the elements in each list. A set only holds unique elements. Then select only the elements shared between both using list.index
def compare(l1, l2):
s1, s2 = set(l1), set(l2)
shared = s1 & s2 # intersection, only the elements in both
return len([e for e in shared if l1.index(e) != l2.index(e)])
You can actually bring this down to a one-liner if you want
def compare(l1, l2):
return len([e for e in set(l1) & set(l2) if l1.index(e) != l2.index(e)])
Alternative:
Functionally you can use the reduce builtin (in python3, you have to do from functools import reduce first). This avoids construction of the list which saves excess memory usage. It uses a lambda function to do the work.
def compare(l1, l2):
return reduce(lambda acc, e: acc + int(l1.index(e) != l2.index(e)),
set(l1) & set(l2), 0)
A brief explanation:
reduce is a functional programming contruct that reduces an iterable to a single item traditionally. Here we use reduce to reduce the set intersection to a single value.
lambda functions are anonymous functions. Saying lambda x, y: x + 1 is like saying def func(x, y): return x + y except that the function has no name. reduce takes a function as its first argument. The first argument a the lambda receives when used with reduce is the result of the previous function, the accumulator.
set(l1) & set(l2) is a set consisting of unique elements that are in both l1 and l2. It is iterated over, and each element is taken out one at a time and used as the second argument to the lambda function.
0 is the initial value for the accumulator. We use this since we assume there are 0 shared elements with different indices to start.
I dont claim it is the simplest answer, but it is a one-liner.
import numpy as np
import itertools
l1 = [1, 2, 3, 4]
l2 = [1, 3, 2, 4]
print len(np.unique(list(itertools.chain.from_iterable([[a,b] for a,b in zip(l1,l2) if a!= b]))))
I explain:
[[a,b] for a,b in zip(l1,l2) if a!= b]
is the list of couples from zip(l1,l2) with different items. Number of elements in this list is number of positions where items at same position differ between the two lists.
Then, list(itertools.chain.from_iterable() is for merging component lists of a list. For instance :
>>> list(itertools.chain.from_iterable([[3,2,5],[5,6],[7,5,3,1]]))
[3, 2, 5, 5, 6, 7, 5, 3, 1]
Then, discard duplicates with np.unique(), and take len().

Categories