Finding Subsets Function to Work for a Multidimensional Array - python

So I have function below that checks to see if any element of list a is the subset of any other element in the same list, and it returns only those indexes that are subsets.
a = [[1,2,3,4],
[2,3],
[1,5,7,8],
[5],
[7,8],
[1,2,3],
[7,8,9]]
#we need to keep [0,2,6]
#we need to remove [1,3,4,5]
def indexes_to_remove(array):
def boolMatrix(array):
boole = []
d ={}
for i,m in enumerate(array):
d[i] = []
for j in array:
boole.append(set(m).issubset(j))
return np.array(boole).reshape(len(array),len(array)) #True equals "is subset"
b= boolMatrix(array)
print(b)
res = [] #indexes to remove
for i,m in enumerate(b):
if sum(m) > 1: #if the index IS a subset of any other index (excludes "True" identity of itself)
res.append(i)
return res
indexes_to_remove(a)
outputs >> [1,3,4,5]
My problem however, is that I need this function to work for a multidimensional array that is
[n X n X 2] whereas a is only [n X n X 1]. For example, I need it to work on something that looks like:
a = [array([[1,2],[1,5],[2,3],[5,7]]),
array([[2,3],[5,7]]),
array([[1,5],[4,5],[9,2]]),
array([[2,3],[4,5],[1,5]])]
which should return [1].
Please help! What change do I need to do to my function for it to work for a multidimensional array of this shape?

Related

How to get triplets from an array?

I have [1,2,3] and I wish to get [(1,1,1), (1,4,9), (1, 8, 27)]. What is the easiest way to achieve this?
I'd probably do this with a list comprehension, an inner loop iterating over your array/list, i. e. [1,2,3] and an outer loop iterating over the powers , i. e. zero, one and two (EDIT: To achieve the output you specified in your question one would need [0,2,3] as powers list):
elements = [1,2,3]
powers = [0,1,2]
[[e**i for e in elements] for i in powers]
The output of this is
[[1, 1, 1], [1, 2, 3], [1, 4, 9]]
If you want a numpy array you can convert it with np.array() and if you want a list of tuples as you have it written in your question convert it with tuple(), i. e.
import numpy as np
elements = [1,2,3]
powers = [0,1,2]
# numpy array
np.array([[e**i for e in elements] for i in powers])
# list of tuples
[tuple([e**i for e in elements]) for i in powers]
I'd do it this way, check it out:
def get_cuadrado_cubo(lista):
resp = []
for i in range (4):
if i == 1:
continue
resp.append((lista [0] ** i, lista [1] ** i, lista [2] ** i) )
return resp

Map a list to a nested list fast

I want to create a function which gives me the corresponding position of the element in a given nested list:
nested_list = [[0,1,2], [4,5], [6,7,8,9], [10]]
So I want to be able to get a function that does this correspondence:
f(6)
#Here, nested_list[2][0] == 6
>> (2,0)
f(2)
#Here, nested_list[2][0] == 2
>> (0,2)
We get a tuple with the corresponding position of an element that is searched using the function.
My current solutions it is not very elegant neither very fast:
from itertools import accumulate
accum_len = list(accumulate([len(l) for l in nested_list]))
def getitem(nested_list, idx):
# first list case
if idx < len(nested_list[0]):
return 0, idx
# other ones in reverse order
for i, l in enumerate(accum_len[::-1]):
if idx >= l:
rel_idx = idx - l
return len(nested_list)-i, rel_idx
Assuming the list is not nested more than once, this should work:
nested_list = [[0,1,2], [4,5], [6,7,8,9], [10]]
def f(n):
return next((i,x.index(n)) for i,x in enumerate(nested_list) if n in x)
f(6)
# (2,0)
f(2)
# (0,2)

Pythonic popping from a list to another list

I have two lists
a = [1,2,3]
b = []
I want to move an element from list a, if it meets a certain condition.
a = [1,3]
b = [2]
The below code shows an example, however, I would like to do this inside of a single loop. How do I do this more efficiently?
a = [1,2,3]
b = []
pop_list = []
for i in range(len(a)):
if a[i] == 2:
print("pop:", a[i])
pop_list.append(i)
for i in range(len(pop_list)):
b.append(a.pop(pop_list[i]))
# Reset pop_list
pop_list=[]
Ideally, I would not generate a new list b.
A pair of list comprehensions would do the job: one to select the desired elements for b, the other to remove them from a
b = [i for i in a if i == 2]
a = [i for i in a if i != 2]
You can use filter and itertools.filterfalse and use the same filtering function for both:
from itertools import filterfalse
a = [1,2,3]
b = []
list(filterfalse(lambda x: x == 2, a))
list(filter (lambda x: x == 2, a))
[1, 3]
[2]
Here is the itertools.filterfalse docs.
If the element x exists you could just remove it from b and append it to a.
a = [1, 2, 3]
b = []
x = 2
def remove_append(a, b, x):
if x in a:
a.remove(x)
b.append(x)
remove_append(a, b, x)
print(a)
print(b)
Output:
[1, 3]
[2]
We must pass through all elements, however, you can apply this trick to add to the appropriate list in one loop:
(Appending to a loop is more efficient than deleting an element at arbitrary position)
a = [1,2,3]
condition_false, condition_true = [], []
for v in a:
# Add to the right list
(condition_false, condition_true)[v == 2].append(v)
# [1, 3]
print(condition_false)
# [2]
print(condition_true)
Here is a single loop way that's similar to your initial method:
length = len(a)
popped = 0
for i in range(length):
if i == length - popped:
break
if a[i] == 2:
b.append(a.pop(i))
popped += 1
If we keep track of how many elements we pop from a, we can just stop our loop that many elements early since there are fewer elements left in a.

Store multiple values in arrays Python

I'm doing a code that needs to store the values of the inputs in two arrays. I'm gonna do a example.
INPUTS: 1,2,3,4,5,6,7,8
Array1= []
Array2= []
What I want to make is store the first value of the input in the array1 and the second in the array2. The final result will be this
Array1=[1,3,5,7]
Array2=[2,4,6,8]
Is possible to do that in python3? Thank you
I tried something like this but doesn't work
arr1,arr2 = list(map(int, input().split()))
You can use the following:
l = [int(x) for x in input().split(',')]
array_1 = l[::2]
array_2 = l[1::2]
So, I assume that you can get the inputs into a list or 'array' using the split? It would be nice to somehow 'map' the values, and numpy probably would offer a good solution. Though, here is a straight forward work;
while INPUTS:
ARRAY1.append(INPUTS.pop())
if INPUTS:
ARRAY2.append(INPUTS.pop())
your attempt:
arr1,arr2 = list(map(int, input().split()))
is trying to unpack evenly a list of 8 elements in 2 elements. Python can unpack 2 elements into 1 or 2, or even use iterable unpacking like:
>>> arr1,*arr2 = [1,2,3,4]
>>> arr2
[2, 3, 4]
but as you see the result isn't what you want.
Instead of unpacking, use a list of lists, and a modulo to compute the proper destination, in a loop:
lst = list(range(1,9)) # or list(map(int, input().split())) in interactive string mode
arrays = [[],[]]
for element in lst:
arrays[element%2].append(element)
result:
[[2, 4, 6, 8], [1, 3, 5, 7]]
(change the order with arrays[1-element%2])
The general case would be to yield the index depending on a condition:
arrays[0 if some_condition(element) else 1].append(element)
or with 2 list variables:
(array1 if some_condition(element) else array2).append(element)
There is my solution in a Class ;)
class AlternateList:
def __init__(self):
self._aList = [[],[]]
self._length = 0
def getItem(self, index):
listSelection = int(index) % 2
if listSelection == 0:
return self._aList[listSelection][int(index / 2)]
else:
return self._aList[listSelection][int((index -1) / 2)]
def append(self, item):
# select list (array) calculating the mod 2 of the actual length.
# This alternate between 0 and 1 depending if the length is even or odd
self._aList[int(self._length % 2)].append(item)
self._length += 1
def toList(self):
return self._aList
# add more methods like pop, slice, etc
How to use:
inputs = ['lemon', 'apple', 'banana', 'orange']
aList = AlternateList()
for i in inputs:
aList.append(i)
print(aList.toList()[0]) # prints -> ['lemon', 'banana']
print(aList.toList()[1]) # prints -> ['apple', 'orange']
print(aList.getItem(3)) # prints -> "orange" (it follow append order)
The pythonic way
Here I have taken some assumptions according to above question:
Given inputs only contain integers.
odd and even are two arrays which contain odd numbers and even numbers respectively.
odd, even = list(), list()
[even.append(i) if i % 2 == 0 else odd.append(i) for i in list(map(int, input().split()))]
print("Even: {}".format(even))
print("Odd: {}".format(odd))

Show common elements in a list and how many times they appeared in python

I need to make a formula that, given two lists a and b, it returns the common elements in a and b. If the same element appears more than once in both, let's say xa times in a and xb times in b, then x should appear min(xa,xb) times in the results. If it's possible, don't use "import" in the code, please.
For example:
(Supposing my function is called common(a,b))
common([1,3,3,3],[1,3,3,3,3,4])
=> [1,3,3,3]
Thank you for your help!
A simple way is sort the two list first and compare the first element one by one. The code is like this:
def common(a, b):
sorted_a, sorted_b = sorted(a), sorted(b)
numa, numb = len(a), len(b)
rv = []
i, j = 0, 0
while i < numa and j < numb:
if sorted_a[i] == sorted_b[j]:
rv.append(sorted_a[i])
i += 1
j += 1
elif sorted_a[i] < sorted_b[j]:
i += 1
else:
j += 1
return rv
def common(lista=None,listb=None):
result_list=list()
inter_dict=dict()
lista_count=dict()
listb_count=dict()
for i in lista:
lista_count[i]=lista_count.get(i,0)+1 #convert lista to dict with frequency
for i in listb:
listb_count[i]=lista_count.get(i,0)+1 #convert listb to dict with frequency
for key in set(lista_count).intersection(set(listb_count)):
inter_dict[key]=min(lista_count[key],listb_count[key]) # get intersection of two dicts
for k,v in inter_dict.items():
result_list.extend([k]*v) #extend to the output list
return result_list
The output will give you when invoke the function common([1,3,3,3],[1,3,3,3,3,4]):
[1, 3, 3, 3]
def common(l1,l2):
totalElements = l1 + l2
resultList = []
for num in totalElements:
if num in l1 and num in l2:
resultList.append(num)
l1.remove(num)
l2.remove(num)
return resultList
l1 = [1,3,3,3,5]
l2 = [1,3,3,3,5,3,4]
result = common(l1 , l2)
print(result)
[1, 3, 3, 3, 5]
Three steps to resolve this problem:
Find out those elements should be in the final list, which is the intersection of two lists
For each element found in step #1, find out how many times it should be in final list
Generate final list based on the info found by previous two steps
And then translate these 3 steps to three lines of code:
def common(l1, l2):
intersection = [e for e in l1 if e in l2]
elemnts_counters = {e: min(l1.count(e), l2.count(e)) for e in intersection}
return sum([[e] * c for e, c in elemnts_counters.items()], [])
Then
print common([1,3,3,3], [1,3,3,3,3,4])
will give you:
[1, 3, 3, 3]

Categories

Resources