matrix duplicate element check with recursive function - python

L = [[1, 2, 3], [4, 3, 6], [7, 8, 1]]
I need a recursive function in python to check the matrix element duplicate. The function should return true if "L" has a row with no duplicate of the same element and false otherwise.

As an academic exercise. No recursion needed.
lst = [
[[1, 2, 3], [4, 3, 6], [7, 8, 1]],
[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
[[1, 2, 3], [4, 8, 6], [7, 8, 9]],
[[1, 2, 3]]
]
for ll in lst:
r = len([x for i,x in enumerate(ll) if [1 for y in ll if len(set(x)&set(y))].count(1) > 1]) == 0
print(r, ll)
Output
False [[1, 2, 3], [4, 3, 6], [7, 8, 1]]
True [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
False [[1, 2, 3], [4, 8, 6], [7, 8, 9]]
True [[1, 2, 3]]
--- Recursive version ---
lst = [
[[1, 2, 3], [4, 3, 6], [7, 8, 1]],
[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
[[1, 2, 3], [4, 8, 6], [7, 8, 9]],
[[1, 2, 3]]
]
def chkdup(lst):
if len(lst) == 1: return True # one list always true
for ls in lst[1:]: # compare other lists
if len(set(lst[0]) & set(ls)): return False # dups found
return chkdup(lst[1:]) # recursion, process next list
for ll in lst: # each list in test data
print(chkdup(ll), ll)
Output
False [[1, 2, 3], [4, 3, 6], [7, 8, 1]]
True [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
False [[1, 2, 3], [4, 8, 6], [7, 8, 9]]
True [[1, 2, 3]]

It is ugly, bulky and needs refactoring, but here you go: (*It is recursive, but recursion seems unnecessary.)
def evaluate_matrix(matrix):
def has_duplicate(arr):
for item in arr:
if arr.count(item) >= 2:
return True
return False
#Here is where all that recursion stuff happens
if len(matrix) <= 1:
return has_duplicate(matrix[0])
else:
return bool(has_duplicate(matrix[0]) + evaluate_matrix(matrix[1:]))
is_double = [[1,2,3,4], [1,1,3,4]]
is_not_double = [5,6,7,8], [[9,10,11,12]]
print("Matrix is_double has a duplicate: ", evaluate_matrix(is_double))
print("Matrix is_not_double has a duplicate: ", evaluate_matrix(is_not_double))

Related

How to join lists inside two or more different lists in arranged order?

I have three lists as follows.
A = [1, 2, 3]; B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]; C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I want to create another list containing all the above inner lists starting from A to C.
Desired = [elements of A, elements of B, elements of C] just like this.
Desired = [[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
It seems like you know which list is nested (B and C) and which isn't (A). If that's the case then you could simply do:
result = [A] + B + C
If you don't know but can determine the nestedness by looking at the first item, then you could do:
result = [
item
for numbers in (A, B, C)
for item in (numbers if isinstance(numbers[0], list) else [numbers])
]
If that's also not the case, i.e. there could be mixed lists (lists that contain numbers and lists), then you could use itertools.groupby from the standard library:
from itertools import groupby
result = []
for key, group in groupby(A + B + C, key=lambda item: isinstance(item, list)):
if not key:
group = [[*group]]
result.extend(group)
Results for all versions (with A, B and C like provided):
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3],
[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
The method I use below is to see if the inner_list contents are infact a list of themselves.
If they are, then append the inner list.
If they are not, then append the outer_list.
A = [1, 2, 3];
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]];
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
desired = []
for outer_list in (A,B,C):
list_state = False
for inner_list in outer_list:
if isinstance(inner_list, list):
desired.append(inner_list)
else:
list_state = True
# Add outer_list only if the inner_list was not a list
if list_state:
desired.append(outer_list)
print(desired)
OUTPUT:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I made something to make a list to an nested list if it is not.
A = [1, 2, 3]
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
listt = [ 'A', 'B', 'C' ]
des = []
for i in listt:
if type((globals()[i])[0]) != list:
globals()[i] = [[i for i in globals()[i]]] #turns into nested list if not (line 7-9)
for i in (A,B,C):
for x in i:
des.append(x)
print(des)
Output:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]

How to get data from nested lists recursively?

I have a nested array of arbitrary length and trying to retrieve data from it in the following order: items in the [0] element of the array form somewhat like a tree and as a result I should return all possible combinations with them.
For example:
some_list = [[1, 2], [3, 4], [5, 6, 7]]
the result should be:
[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7],
[2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]
I tried loops but they do not seem a good decision.
I think it should be recursion, but don't know how to apply it.
this is an example of a recursive function that would calculate the cartesian product of all the input lists
def cp(x):
l = []
# loop over the lists in the list
# if there is only 1 list left in the input then return it
if len(x) > 1:
for i in x[0]: # loop over the first list in the input
for j in cp(x[1:]): # loop over the cartesian product of the remaining lists in the input
l.append([i]) # add a new sub-list starting with value of i
if isinstance(j,list): # extend it with the result of the cartesian product of the remaining lists
l[-1].extend(j)
else:
l[-1].append(j)
else:
l = x[0]
return l
print(cp([[1, 2], [3, 4], [5, 6, 7]]))
gives the output
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]
have a look here for implementations in different programming languages:
https://rosettacode.org/wiki/Cartesian_product_of_two_or_more_lists
You can do it with nested for loops, or for convenience, with itertools.product:
from itertools import product
some_list = [[1, 2], [3, 4], [5, 6, 7]]
prod = [list(i) for i in product(*some_list)]
print(prod)
Output:
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]

List item arrangement in python

I am looking for an efficient way to transform a given list into another list with degree n
here is input:
lst = [1, 2, 3, 4, 5, 6, 7]
n = 3
And favorable output is this:
[[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
It is basically like every element in resulting list is made of n consecutive elements from the given list except elements at starting and ending n-1 indices: 1, 2, 6, 7 in this example
Also for integer n, 1 <= n <= len(lst) is essential
You can use a comprehension with appropriate slices:
def chunks(lst, n=3):
return [lst[max(i,0):i+n] for i in range(1-n, len(lst))]
chunks([1, 2, 3, 4, 5, 6, 7])
# [[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
chunks([1, 2, 3, 4, 5], 4)
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5]]
chunks([1, 2], 2)
# [[1], [1, 2], [2]]
chunks([1, 2, 3], 1)
# [[1], [2], [3]]
A more elegant version of this sliding window uses a collections.deque (as pointed out by #chepner in the comments):
from collections import deque
def chunks(lst, n=3):
window = deque(maxlen=n)
for x in lst:
window.append(x)
yield list(window)
while len(window) > 1:
window.popleft()
yield list(window)

How to remove lists from a list

I have created a list where within it I seek to eliminate only the lists whose first value is greater than the second value of it.
I tried creating a second list with the elements to remove but I think it is not the most optimal way.
#y = []
x = [[1, 4], [1, 6], [2, 5], [2, 7], [4, 8], [6, 5], [6, 7], [2, 6], [3, 7], [5, 8], [6, 4], [7, 5]]
for i in range(len(x)):
if x[i][0] > x[i][1]:
print(x[i])
# y.append(x[i])
Is there an optimal way to achieve this?
I want that when printing on screen you get the following:
[[1, 4], [1, 6], [2, 5], [2, 7], [4, 8], [6, 7], [2, 6], [3, 7], [ 5, 8]]
Best regards,
This should work:
y = [[a,b] for a,b in x if a <= b]
Testing:
>>> x = [[1, 4], [1, 6], [2, 5], [2, 7], [4, 8], [6, 5], [6, 7], [2, 6], [3, 7], [5, 8], [6, 4], [7, 5]]
>>> y = [[a,b] for a,b in x if a < b]
>>> y
[[1, 4], [1, 6], [2, 5], [2, 7], [4, 8], [6, 7], [2, 6], [3, 7], [5, 8]]
>>>
This modifies the original list:
for i, (a, b) in enumerate(x):
if a > b:
del x[i]
Creating a new list:
[v for v in x if v[0] <= v[1]]
Or elimination in place:
for i in range(len(x) - 1, -1, -1): # need to start at the end
if x[i][0] > x[i][1]:
x.pop(i)
>>> filtered = list(filter(lambda f: f[0] < f[1], x))
>>> print(filtered)
This will create a new list with the desired values, using the built in filter(function, iterable) function.

How to select all possible sub-list pairs from a given list whose union will be the list?

Given a list say [4,5,6,7] i want to write a function that will output
all pairs like ([4,5,7],[6]) ,( [4,5] , [6,7])
length of sub-list are not fixed
i used a for loop and two new lists to append ith element to list one
and append the remaining to list 2 then repeat the process i know this is a silly approach
a = [4,5,6,7]
for x in range(0,len(a)):
b = []
c = []
b.append(a[x])
for y in range(0,len(a)):
if y!=x:
c.append(a[y])
print(b,c)
for x in range(0,len(a)-1):
b = []
c = []
b.append(a[x])
b.append(a[x+1])
for y in range(0,len(a)):
if y!=x and y!=x+1:
c.append(a[y])
print(b,c)
i expect to print all possible sub-lists but always miss the non contiguous ones , i get( [4, 5 ] , [6,7] ) but never generate
([4,6],[5,7])
Here is a solution that does not remove duplicates:
from itertools import combinations
a = [4,4,5,6,7]
result = []
for x in range(len(a) + 1):
for left in combinations(a, x):
right = a.copy()
for ele in left:
right.remove(ele)
result.append([list(left), right])
for res in result:
print(res)
Output:
[[], [4, 4, 5, 6, 7]]
[[4], [4, 5, 6, 7]]
[[4], [4, 5, 6, 7]]
[[5], [4, 4, 6, 7]]
[[6], [4, 4, 5, 7]]
[[7], [4, 4, 5, 6]]
[[4, 4], [5, 6, 7]]
[[4, 5], [4, 6, 7]]
[[4, 6], [4, 5, 7]]
[[4, 7], [4, 5, 6]]
[[4, 5], [4, 6, 7]]
[[4, 6], [4, 5, 7]]
[[4, 7], [4, 5, 6]]
[[5, 6], [4, 4, 7]]
[[5, 7], [4, 4, 6]]
[[6, 7], [4, 4, 5]]
[[4, 4, 5], [6, 7]]
[[4, 4, 6], [5, 7]]
[[4, 4, 7], [5, 6]]
[[4, 5, 6], [4, 7]]
[[4, 5, 7], [4, 6]]
[[4, 6, 7], [4, 5]]
[[4, 5, 6], [4, 7]]
[[4, 5, 7], [4, 6]]
[[4, 6, 7], [4, 5]]
[[5, 6, 7], [4, 4]]
[[4, 4, 5, 6], [7]]
[[4, 4, 5, 7], [6]]
[[4, 4, 6, 7], [5]]
[[4, 5, 6, 7], [4]]
[[4, 5, 6, 7], [4]]
[[4, 4, 5, 6, 7], []]
You can use itertools module to construct all such sublists:
import itertools as it
s = {4,5,6,7}
for length in range(len(s)):
for combination in it.combinations(s, length):
print(list(combination), list(s - set(combination)))
[] [4, 5, 6, 7]
[4] [5, 6, 7]
[5] [4, 6, 7]
[6] [4, 5, 7]
[7] [4, 5, 6]
[4, 5] [6, 7]
[4, 6] [5, 7]
[4, 7] [5, 6]
[5, 6] [4, 7]
[5, 7] [4, 6]
[6, 7] [4, 5]
[4, 5, 6] [7]
[4, 5, 7] [6]
[4, 6, 7] [5]
[5, 6, 7] [4]
You can make a random sublist, then get the elements on the second list that are not iun the random sublist:
def get_from_0_to_len_minus_1_elements_from_original_list():
pass # You implement this
list1 = get_from_0_to_len_minus_1_elements_from_original_list()
list2 = [element for element in original_list if element not in list1]
print(list1, list2)
As to how you partition the original list into random chunks that is up to you to solve

Categories