This question already has answers here:
Sorting list based on values from another list
(20 answers)
Closed 11 months ago.
Say I have two lists: test (1st one which will be the sorted one), and sort (which is the sorting index of the other list):
test
[16, 44, 12, 43, 17, 22, 6, 20, 41, 21]
sort
[20, 40, 43, 41, 29, 2, 14, 27, 44, 16 42, 21, 3, 22, 9, 32, 17, 23, 1,
31, 24, 19, 10, 33, 25, 26, 5, 30, 12, 28, 18, 8, 6, 15, 7, 13, 11, 4]
How can I sort test based on the matrix position? This would be my desired solution:
[20, 43, 41, 44, 16, 21, 22, 17, 12, 6]
Edit: I see there are many alike questions like mine, I tried a solution from Sorting list based on values from another list, which is the following:
[x for _, x in sorted(zip(test, sort))]
[14, 43, 20, 29, 27, 16, 2, 44, 41, 40]
As it can be seen, this is not equal to my desired output as 20 should be on the first place.
You can do this with list comprehension or looping over the matrix element to check each iteration if it belongs in the test array.
Example using list comprehension:
test = [16, 44, 12, 43, 17, 22, 6, 20, 41, 21]
matrix = [20, 40, 43, 41, 29, 2, 14, 27, 44, 16]
result = [i for i in matrix if i in test]
Example with normal append:
test = [16, 44, 12, 43, 17, 22, 6, 20, 41, 21]
matrix = [20, 40, 43, 41, 29, 2, 14, 27, 44, 16]
result = []
other = []
for i in matrix:
if i in test:
result.append(i)
# Edit: if you want to keep the remaining ones in default sorting
else:
other.append(i)
result.extend(other)
Edit: updated the for loop to append everything not in test to another array. When the result array extend() that one, they would be combined. If this is what you're looking for, the list comprehension example here will not give the expected result.
I have an ordered Python list of forms:
[1, 2, 3, 4, 5, 12, 13, 14, 15, 20, 21, 22, 23, 30, 35, 36, 37, 38, 39, 40]
How can I group together consecutive numbers in a list. A group like this:
[[1, 2, 3, 4, 5], [12, 13, 14, 15], [20, 21, 22, 23,], [30], [35, 36, 37, 38, 39, 40]]
I tried using groupby from here but was not able to tailor it to my need.
Thanks,
You could use negative indexing:
def group_by_missing(seq):
if not seq:
return seq
grouped = [[seq[0]]]
for x in seq[1:]:
if x == grouped[-1][-1] + 1:
grouped[-1].append(x)
else:
grouped.append([x])
return grouped
Example Usage:
>>> lst = [1, 2, 3, 4, 5, 12, 13, 14, 15, 20, 21, 22, 23, 30, 35, 36, 37, 38, 39, 40]
>>> group_by_missing(lst)
[[1, 2, 3, 4, 5], [12, 13, 14, 15], [20, 21, 22, 23], [30], [35, 36, 37, 38, 39, 40]]
A fancy pythonic way to do it with less lines would be possible with the reduce function from functools and a lambda function with an inline if as a criteria for the reduce:
import functools
lis = [1, 2, 3, 4, 5, 12, 13, 14, 15, 20, 21, 22, 23, 30, 35, 36, 37, 38, 39, 40]
result = functools.reduce(lambda x,y : x[:-1]+[x[-1]+[y]] if (x[-1][-1]+1==y) else [*x,[y]], lis[1:] , [[lis[0]]] )
print(result)
I'm using Python to create a 12*12 multiplication table.
The table is held in memory in a nested list multi_table, where:
multi_table[0][0] holds “X”
The first row holds the number i for every position i
The first column holds the number j for every position j
each product i*j is stored in position multi_table[i][j].
The multiplication table is shown in Figure 1 below.
Figure 1: Multiplication Table
Umm, what is the question? By how to format do you mean how to generate this nested list?
If so, how about:
n = 12
table = [['X'] * (n+1) for _ in range(n+1)]
for i in range(1, n+1):
table[i][0] = i
for j in range(1, n+1):
table[0][j] = j
table[i][j] = i*j
table
[['X', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
[3, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
[4, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48],
[5, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60],
[6, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72],
[7, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84],
[8, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96],
[9, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99, 108],
[10, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
[11, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110, 121, 132],
[12, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144]]
looking for something in python's standard lib or a syntax trick.
for non-clojure programmers, partition-all should have these semantics:
partition_all(16, lst) == [lst[0:16], lst[16:32], lst[32:48], lst[48:60]]
assuming len(lst) == 60
There is no such function in Python. You can do this:
from itertools import islice
def chunkwise(n, iterable):
it = iter(iterable)
while True:
chunk = list(islice(it, n))
if not chunk:
break
yield chunk
print list(chunkwise(3, range(10)))
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
Adding a third "step size" parameter to the range built-in function gets you pretty close:
>>> range(0,60,16)
[0, 16, 32, 48]
You can create tuples for the upper and lower bounds from there:
>>> [(i, i+16) for i in range(0, 60, 16)]
[(0, 16), (16, 32), (32, 48), (48, 64)]
Or create the actual ranges if you need them:
>>> [range(i, i+16) for i in range(0, 60, 16)]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]]
Naturally you can parameterize the 0, 60, and 16 into your own function if you need to.
I don't think there is a partition_all like function in the standard library so I'm afraid you are writing your own. However looking at https://github.com/clojure/clojure/blob/b578c69d7480f621841ebcafdfa98e33fcb765f6/src/clj/clojure/core.clj#L5599 I'm thinking you could implement it in Python like this:
>>> from itertools import islice
>>> lst = range(60)
>>> def partition_all(n, lst, step=None, start=0):
... step = step if step is not None else n
... yield islice(lst, start, n)
... while n < len(lst):
... start, n = start + step, n + step
... yield islice(lst, start, n)
...
>>>
>>> for partition in partition_all(16, lst):
... l = list(partition)
... print len(l), l
...
16 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
16 [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
16 [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
12 [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
>>>
The recipes section of the itertools documentation has a grouper function that does what you want.
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
Beware that there's also a recipe for "partition", but that does something different.
I believe I have a shorter answer which does not require importing any libraries.
Here is a one-liner for you:
>>> lst = list(range(60))
>>> [lst[i * 16: (i + 1) * 16] for i in range(len(lst) / size + int((len(lst) % 16) > 0)))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]]
Now as a function (assumes that you work with a list):
def partition(lst, size):
assert(size >= 0)
if not lst: return ()
return (lst[i * size: (i + 1) * size] for i in range(len(lst) / size + int((len(lst) % size) > 0)))
>>> partition(list(range(78)), 17)
<generator object <genexpr> at 0x7f284e33d5a0>
>>> list(partition(list(range(78)), 17))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], [34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], [68, 69, 70, 71, 72, 73, 74, 75, 76, 77]]
>>> list(partition(range(16), 4))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
>>> print list(partition(range(0), 4))
[]
EDIT: New solution based on Triptych's answer:
def partition(lst, size):
assert(size >= 0)
if not lst: return ()
return (lst[i: i + size] for i in range(0, len(lst), size))
>>> partition(list(range(78)), 17)
<generator object <genexpr> at 0x025F5A58>
>>> list(partition(list(range(78)), 17))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33], [34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67], [68, 69, 70, 71, 72, 73, 74, 75, 76, 77]]
>>> list(partition(list(range(16)), 17))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]]
>>> list(partition(list(range(16)), 4))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
>>> list(partition([], 17))
[]
>>>