Related
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?
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.
I have two lists,
In the first list I have all the information:
list1 = ['node1=6d', 'node2=10d', 'node3=5d']
In the second I just have the days:
list 2 = [6, 10, 5]
Is there a way to take the position from the indexes of the second one, that are <=7 ? (For example) and then print those with the same position of the list1?
Example:
Values of list2 that are <= 7:
Position 0, 2
Then print from list one those values with the position 0, 2
Output should be:
['node1=6d', 'node3=5d']
Original answer:
from operator import itemgetter
idx = [i for i, n in enumerate(list2) if n <= 7]
result = itemgetter(*idx)(list1)
print(result)
To get the list item indices according to a condition, you can just use a list comprehension:
idx = [i for i, n in enumerate(list2) if n <= 7]
If you wish to retrieve the values using the indices, you have several options, some of which are:
Using itemgetter:
Return a callable object that fetches item from its operand using the operand’s getitem() method. If multiple items are specified, returns a tuple of lookup values.
[Python Documentation]
from operator import itemgetter
result = itemgetter(*idx)(list1)
print(result)
('node1=6d', 'node3=5d')
Using a list comprehension again:
result = [list1[i] for i in idx]
Directly invoking __getitem__ (This is not a best practice!):
Called to implement evaluation of self[key]...
[Python Documentation]
result = list(map(list1.__getitem__, idx))
Bonus: If you wish to use numpy at some point, this would be a convenient solution:
import numpy as np
# Creating numpy arrays
list1 = np.array(['node1=6d', 'node2=10d', 'node3=5d'])
list2 = np.array([6, 10, 5])
# Getting the indices
idx = np.where(list2 <= 7)
# Getting all the values at once and converting the array into a list
result = list(list1[idx])
You can try this:
days_condition = 7
index_output = [index for index,val in enumerate(list_2) if val<=days_condition]
"Positions: "+",".join(map(str, index_output))
## you can access the list1 using the index_output
[list1[index] for index in index_output]
output:
'Positions 0,2'
['node1=6d', 'node3=5d']
You can use zip()
res = [x for x, y in zip(list1, list2) if y < 8]
print(res)
#['node1=6d', 'node3=5d']
I'm trying to create a set of test cases for a project I'm working on, and I'd like to create all possible test cases and iterate through them (quick program, shouldn't take long). The test cases should all be a list of length 1-4 and each item on the list should be an integer between 0-10, inclusive. The first item on the list should be 0. The set of lists would then be:
[0]
[0,0]
[0,1]
[0,2]
[0,3]
...
[0,10]
[0,0,0]
[0,0,1]
[0,0,2]
[0,0,3]
...
[0,1,0]
[0,1,1]
[0,1,2]
...
[0,10,10]
...
[0,10,10,10]
This is what I have so far, but it's not outputting the correct lists:
test_list = [0]
for length in range(2, 5):
while len(test_list) < length:
test_list.append(0)
for position in range(1, length):
for digit in range (0, 11):
test_list[position] = digit
print test_list
or you could generate the lists with a generator; this way you would not have the whole list in memory:
from itertools import product
def gen():
yield [0]
for i in range(11):
yield [0, i]
for i, j in product(range(11), range(11)):
yield [0, i, j]
for i, j, k in product(range(11), range(11), range(11)):
yield [0, i, j, k]
for item in gen():
print(item)
this seems pretty readable to me but is not extensible (in case you need longer lists) as other answers here.
therefore here the version where the length of the list is tweakable:
from itertools import product
def gen(length):
for l in range(length):
for tpl in product(range(11), repeat=l):
yield (0,) + tpl
for item in gen(length=4):
print(item)
this version now returns tuples and not lists. in case this matters you can surrout the return values with list().
I would use itertools.product on lists of size 2, 3, 4 in a nested loop
import itertools
test_list = [0]
for i in range(1,4):
args = [list(range(0,11))] *i
test_list += [[0]+list(x) for x in itertools.product(*args)]
# display list
for t in test_list:
print(t)
A memory efficient one-liner :
import itertools
size = 4
for x in map(list, itertools.chain(*(itertools.product([0], *[range(11)]*i) for i in range(size)))):
print(x)
You can modify 4 with any other list size :)
I have to find the longest list inside a list of lists.
For example:
longest([1,2,3]) returns 3
longest([[[1,2,3]]]) also returns 3 (inner list is 3)
longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]]) returns 7 (list [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]] contains 7 elements)
Right now I have this code, but it doesn't do the trick with the first two examples.
def longest(list1):
longest_list = max(len(elem) for elem in list1)
return longest_list
Maybe recursion will help?
These simple few lines works for me, my list is a nested one (list of lists)
#define the function#
def find_max_list(list):
list_len = [len(i) for i in list]
print(max(list_len))
#print output#
find_max_list(your_list)
Here is a recursive solution for any depth list:
def longest(l):
if not isinstance(l, list):
return 0
return max(
[len(l)]
+ [len(subl) for subl in l if isinstance(subl, list)]
+ [longest(subl) for subl in l]
)
Python 3.3 version:
def lengths(x):
if isinstance(x,list):
yield len(x)
for y in x:
yield from lengths(y)
usage:
>>> l = [[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]]
>>> max(lengths(l))
7
In python 2.6+ you don't have the yield from statement (was introduced in python 3.3), so you have to change the code slightly:
def lengths(x):
if isinstance(x,list):
yield len(x)
for y in x:
for z in lengths(y):
yield z
Indeed, recursion can solve this.
def longest(lst):
if type(lst) is not list:
return 0
max = len(lst)
for i in lst:
max_i = longest(i)
if max_i > max:
max = max_i
return max
You can make use of enumerate, sorted and behavior of list:
ll = [[10,20], [1,2,3,4,5], [7,8,9]]
longest = ll[sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]]
>>longest
>>[1,2,3,4,5]
Explanation
Create list of tuple with index as first element and len(l) (length of list) as second element:
[(i,len(l)) for i,l in enumerate(ll)]
>>[(0, 2), (1, 5), (2, 3)]
Sort above list by second element in tuple that tuple with longest length gets to the end of the list:
sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])
>>[(0, 2), (2, 3), (1, 5)]
Catch the last tuple and its first element:
sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]
>>1
Use above result as the index in ll to get the longest list:
ll[sorted([(i,len(l)) for i,l in enumerate(ll)], key=lambda t: t[1])[-1][0]]
>>[1,2,3,4,5]
The following will give you the indices of longest link:
import numpy as np
def find_max_list_idx(list):
list_len = [len(i) for i in list]
return np.argmax(np.array(list_len))
Example
a=[[1],[1,2,3],[3,4]]
print(find_max_list_idx(a))
'''
it will print index 1 as output
'''
You can do this with recursion:
def longest(list1) :
l = 0
if type(list1) is list :
l = len(list1)
if l > 0 :
l = max(l,max(longest(elem) for elem in list1))
return l
(online demo).
The code first checks if this is list we are dealing with. If so, we first take the len of the list. Next we perform a recursive call on its elements. And calculate the maximum longest of the elements. If the maximum is greater than the length itself. We return that maximum, otherwise we return the length.
Because the longest of a non-list is zero, the recursion will stop, and we have an answer for single elements to be used in the inductive step.
Another recursive function using map:
def longest(a):
return max(len(a), *map(longest, a)) if isinstance(a, list) and a else 0
In [2]: longest([1,2,3])
Out[2]: 3
In [3]: longest([[[1,2,3]]])
Out[3]: 3
In [4]: longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]])
Out[4]: 7
and iteratively:
def longest(a):
mx = 0
stack = [a[:]]
while stack:
cur = stack.pop()
if isinstance(cur, list):
mx = max(mx, len(cur))
stack += cur
return mx
In [6]: longest([1,2,3])
Out[6]: 3
In [7]: longest([[[1,2,3]]])
Out[7]: 3
In [8]: longest([[], [3,[4,5],[2,3,4,5,3,3], [7], 5, [1,2,3], [3,4]], [1,2,3,4,5]])
Out[8]: 7
Using the toolz library, this can be achieved like this:
from toolz.curried import count
def longest(your_list):
return max(map(count, your_list))
One caveat: This doesn't work if your_list contains non-iterables.
Needs only one line:
max([len(i) for i in lst)])
When lst is a list of lists.