Map arrays to integers in python - python

I have an array [[0, 1, 1], [1, 0, 0], [1, 1, 0], [0, 1, 1], [1, 0, 0]] and I want to get this [[0], [1], [2], [0], [1]] - so I want to specify all the same vectors with unique number.
I have an idea how to do it, but it is really ugly, pretty slow and not pythonic at all. How could I do it more pythonic and nicer?
def get_multiclass_list_nodes(y_):
_class = 0
prev_list = list()
new_y = list()
for el in y_:
el = el.astype('int32').tolist()
if el in prev_list:
index = -1
for i, val in enumerate(prev_list):
if val == el:
index = i + 1
break
new_y.append([index])
else:
_class += 1
prev_list.append(el)
new_y.append([_class])
return np.array(new_y)

This should work for you:
def map_lists_to_ints(list_of_lists): # Name this better
tuples = (tuple(l) for l in list_of_lists)
seen = {}
next_int = 0
for tup in tuples:
if tup not in seen:
seen[tup] = next_int
next_int += 1
yield seen[tup]
list_of_lists = [[0, 1, 1], [1, 0, 0], [1, 1, 0], [0, 1, 1], [1, 0, 0]]
result = list(map_lists_to_ints(list_of_lists))
print(result)
listified_result = [[x] for x in result]
print(listified_result)
Output:
[0, 1, 2, 0, 1]
[[0], [1], [2], [0], [1]]

Maybe this is abusing numpy a bit, but an easy way:
a = np.array([[0, 1, 1], [1, 0, 0], [1, 1, 0], [0, 1, 1], [1, 0, 0]])
lst = [str(x) for x in a]
result = np.unique(lst, return_inverse=True)[1]
Perhaps you'll want to tweak the final result, but it's trivial from there.

Related

Searching within Nested lists in Python || How do I match a 1-index nested list, with a 2-index nested list

here is the problem I am trying to solve:
coord = [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 1], [2, 2] ..]
new_arr = [[[0, 0], 1], [[1, 0], 1], [[1, 1], 1], [[2, 0], 1], [[2, 1], 2], [[2, 2], 1] ..]
This is the target I am trying to map to
[0, 0][0, 1][0, 2]
[1, 0][1, 1][1, 2]
[2, 0][2, 1][2, 2]
the ultimate output would be the counts against each of the coordinates
1 0 0
1 1 0
1 2 1
------ clarifications --------
the goal is to generate this square of numbers (counts) which is the second element in new_arr. E.g. [[0, 0], 1], [[1, 0], 1], can be interpreted as the value 1 for the coordinate [0,0] and value 1 for coordinate [1,0] 
the first list (coord) is simply a map of the coordinates. The goal is to get the corresponding value (from new_arr) and display it in the form of a square. Hope this clarified. The output will be a grid of the format
1 0 0
1 1 0
1 2 1
to the question of N (I just took a sample value of 3). The actual use case is when the user enters an integer, say 6 and the result is in a 6 X 6 square. The counts are chess move computations on the ways to reach a specific cell (two movements only (i+1, j) & (i+1, j+1) ....... starting from (0,0)
The logic is not fully clear, but is looks like you want to map the values of new_arr on the Cartesian product of coordinates:
N = 3 # how this is determined is unclear
d = {tuple(l):x for l, x in new_arr}
# {(0, 0): 1, (1, 0): 1, (1, 1): 1, (2, 0): 1, (2, 1): 2, (2, 2): 1}
out = [d.get((i,j), 0) for i in range(N) for j in range(N)]
# [1, 0, 0, 1, 1, 0, 1, 2, 1]
# 2D variant
out2 = [[d.get((i,j), 0) for j in range(N)] for i in range(N)]
# [[1, 0, 0],
# [1, 1, 0],
# [1, 2, 1]]
alternative with numpy
import numpy as np
N = 3
a = np.zeros((N,N), dtype=int)
# get indices and values
idx, val = zip(*new_arr)
# assign values (option 1)
a[tuple(zip(*idx))] = val
# assign values (option 2)
a[tuple(np.array(idx).T.tolist())] = val
print(a)
output:
array([[1, 0, 0],
[1, 1, 0],
[1, 2, 1]])
Use numpy:
import numpy as np
i = []
coord = [[0, 0], [1, 0], [1, 1], [2, 0], [2, 1], [2, 1], [2, 2]]
new_arr = [[[0, 0], 1], [[1, 0], 1], [[1, 1], 1], [[2, 0], 1], [[2, 1], 2], [[2, 2], 1]]
result = np.zeros([coord[-1][0] + 1, coord[-1][1] + 1])
for i in new_arr:
for j in coord:
if i[0] == j:
result[j[0],j[1]]= i[1]
print(result)
Output:
[[1. 0. 0.]
[1. 1. 0.]
[1. 2. 1.]]

Find all possible replacements for 1s and 0s in a list

Input:
table = [
[1, ''],
['', 0]
]
Desired output:
[[[1, 0], [0, 0]], [[1, 0], [1, 0]], [[1, 1], [0, 0]], [[1, 1], [1, 0]]]
Tried to do it with recursion like this:
def get_tables(tab, out_tab):
changes = 0
for row_i, row in enumerate(tab):
for val_i, val in enumerate(row):
if val == '':
changes = 1
tab[row_i][val_i] = 0
get_tables(tab, out_tab)
tab[row_i][val_i] = 1
get_tables(tab, out_tab)
if changes == 0:
out_tab.append(tab)
But it returns only 1s
Edit:
So the logic is: find '' in list and then create two lists, one with 1 instead of '' and one with 0 (like [1, ''] to [1, 0] and [1, 1]). Do the same operation with those two lists, and continue until there's no ''. Return all this lists in one.
Not the most efficient solution, but it works:
table = [
[1, ''],
['', 0]
]
import copy
# locations where element is ''
locs = [[idx_r, idx_c] for idx_r, row in enumerate(table) for idx_c, element in enumerate(row) if element == '']
len_locs = len(locs)
tables = []
for i in range(2 ** len_locs): # for n locations, we have 2**n permutations of 1 and 0
table_copy = copy.deepcopy(table)
permutation = list(map(int, f'{i:0{len_locs}b}')) # convert i to the binary to get current permutation
for it, (idx_r, idx_c) in enumerate(locs):
table_copy[idx_r][idx_c] = permutation[it]
tables.append(table_copy)
print(tables)
>>> [[[1, 0], [0, 0]], [[1, 0], [1, 0]], [[1, 1], [0, 0]], [[1, 1], [1, 0]]]

Determine which combinations of vectors will sum to another vector

I am using Python 3 to try to find what linear combinations of a set of vectors will sum to another vector. I am using numpy arrays as vectors.
For example, I would have a target vector and matrix "choices" containing all the possible choices of vectors:
targetvector0 = numpy.array([0, 1, 2])
choices = numpy.array([[0, 1, 0], [0, 0, 1], [0, 0, 2], [1, 1, 0]])
I need something that would return all possible combinations and their integer multiples (need them to be integer multiples) that sum to the target and ignore those that don't:
option1 = [[1], [2], [0], [0]]
option2 = [[1], [0], [1], [0]]
I found some info on numpy.linalg.solve(x, y), but it doesn't quite do what I'm looking for or I don't know how to use it effectively.
I suppose the multiples you are searching are all positive.
You can carefully increment the multiples, studying all the combinations that give results not greater than the target vector.
import numpy as np
def solve(target_vector, choices):
nb_choices, n = choices.shape
factors = np.zeros((1, nb_choices), dtype=np.int)
i = 0
while True:
if i == nb_choices - 1:
return
factors[0, i] += 1
difference_to_target = factors.dot(choices) - targetvector
found_solution = np.all(difference_to_target == 0)
factors_too_high = np.any(difference_to_target > 0)
if found_solution:
yield factors.copy()
if found_solution or factors_too_high:
factors[0, :i + 1] = 0
i += 1
continue
i = 0
targetvector = np.array([0, 1, 2])
choices = np.array([[0, 1, 0], [0, 0, 1], [0, 0, 2], [1, 1, 0]])
print(list(solve(targetvector, choices)))
# [array([[1, 2, 0, 0]]), array([[1, 0, 1, 0]])]

Generate all possible lists by replacing elements with 0

I would like to create from a list all the different list were 0,1,2,3...all element are replaced by an other
For example, if the replacement item is 0:
L=[1,2,3]
->[1,2,3],[0,2,3],[1,0,3],[1,2,0],[0,0,3],[0,2,0],[1,0,0],[0,0,0]
So far, I've tried I managed to do what I whant using Itertools but only in the case where 1 value is replaced by 0
Does anyone know how to do this ?
Everyone's trying too hard here. We want each value to be either the original value or 0 -- we want pairs like (1,0), (2,0), and (3,0):
>>> from itertools import product, repeat
>>> L = [1, 2, 3]
>>> zip(L, repeat(0))
<zip object at 0x7f931ad1bf08>
>>> list(zip(L, repeat(0)))
[(1, 0), (2, 0), (3, 0)]
and then we can just pass that into product:
>>> list(product(*zip(L, repeat(0))))
[(1, 2, 3), (1, 2, 0), (1, 0, 3), (1, 0, 0), (0, 2, 3), (0, 2, 0), (0, 0, 3), (0, 0, 0)]
This is one way using itertools. The benefit of this method is that it is lazy.
A new list is produced on every __next__ call of the generator transformer.
Alternatively, as below, you can output all combinations by calling list on the generator function.
from itertools import combinations, chain
A = [1, 2, 3]
def transformer(x):
idx = chain.from_iterable(combinations(range(len(x)), i) for i in range(len(x)+1))
for indices in idx:
y = x.copy()
for j in indices:
y[j] = 0
yield y
res = list(transformer(A))
print(res)
[[1, 2, 3], [0, 2, 3], [1, 0, 3], [1, 2, 0], [0, 0, 3], [0, 2, 0], [1, 0, 0], [0, 0, 0]]
You can use recursion. First, create a function that can generate a full combinations for each index of the input:
def full_combinations(d, current = []):
if len(d) == len(current):
yield current
else:
yield current
for i in range(len(d)):
if len(set(current+[i])) == len(current)+1:
yield from full_combinations(d, current+[i])
combination_list = list(full_combinations([1, 2, 3]))
new_results = [[0 if c in i else a for c, a in enumerate([1, 2, 3])] for i in combination_list]
full = [a for i, a in enumerate(new_results) if a not in new_results[:i]]
Output:
[[1, 2, 3], [0, 2, 3], [0, 0, 3], [0, 0, 0], [0, 2, 0], [1, 0, 3], [1, 0, 0], [1, 2, 0]]
It's not pretty, but I'm sure you can get this idea to work.
The idea is to use itertools.combinations to get all combinations of indices for every length, then we flatten this list with itertools.chain().
Then we loop through this list of lists, setting those indices to the replace character.
import itertools
l = [1,2,3]
replace = 0
indices = list(itertools.chain(*[list(itertools.combinations(list(range(len(l))),z+1)) for z in range(len(l))]))
allcombs = [[l]]
for i in indices:
l2 = l[:]
for j in i:
l2[j] = replace
allcombs.append(l2)
print(allcombs)
[[[1, 2, 3]], [0, 2, 3], [1, 0, 3], [1, 2, 0], [0, 0, 3], [0, 2, 0], [1, 0, 0], [0, 0, 0]]

How can I change the view of my list?

Good evening! I have the following code which works when you write
python new.py -s 13 -p 5 on the command prompt.
What command prompt prints is :
[[1, [0], [0]], [1, [0], [0]], [1, [0], [0]], [1, [0]], [1, [0]]]
But I wanted:
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0], [1, 0]]
How can I do this?
-s 12 is the length of the string and -p 7 the 1s.
Thank you!
My code sample :
import argparse
p = argparse.ArgumentParser()
p.add_argument("-pulses", help = "number of pulses", type = int)
p.add_argument("-slots", help = "length of the rythm", type = int)
args = p.parse_args()
slots = args.slots
pulses = args.pulses
pauses = slots - pulses
mod = slots % pulses
rhythm = []
if mod != 0:
i = 0
j = 0
temp = []
while i < pulses:
rhythm.append([1])
i = i + 1
while j < pauses:
rhythm.append([0])
j = j + 1
m = slots
n = pauses
while (rhythm[-1]==[0]):
if (n!=0):
step = m%n
hlp = n
m = n
n = step
i = 0
while (i<step):
rhythm[i].append(rhythm[-1])
rhythm.remove(rhythm[-1])
i = i + 1
print (rhythm)
Note: This is a mere copy&paste from the comment.
Check this out.
I haven't fully analyzed your code but I believe your problem resides in append(). Try to replace it for extend().
The Problem is this line
rhythm[i].append(rhythm[-1])
rhythm[-1] returns a list ([0] or [1]). So you must use extend instead of append.
rhythm[i].extend(rhythm[-1])
Python List
Woozy Coder definitively correctly answered this question.
More generally speaking about lists appending and extending:
dest_list.append(appended_item) appends an item to the list. Should the appended item be a list, this list will be appended as is, and becomes an additional item at the end of the destination list.
dest_list.extend(list_extension) extends a list with another list, every item of this other list being individually appended to the end of the destination list.
Your code seems overly complicated. I think the code below does what you're trying to do:
def rhythm_list(slots, pulses):
q, r = divmod(slots, pulses)
full = [1] + [0] * q
part = full[:-1]
return [full] * r + [part] * (pulses - r)
# Test
print(rhythm_list(13, 5))
print(rhythm_list(12, 7))
print(rhythm_list(12, 4))
output
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0], [1, 0]]
[[1, 0], [1, 0], [1, 0], [1, 0], [1, 0], [1], [1]]
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
Note that the output list contains duplicated references to the full and part lists, so if you do:
m = rhythm_list(12, 7)
m[0][0]=2
then m becomes:
[[2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [1], [1]]
If this behaviour is undesirable, then change the last line of rhythm_list to
return [full[:] for _ in range(r)] + [part[:] for _ in range(pulses - r)]

Categories