Get list for duplicates on an other list python - python

I need help to get a list from an other :
input :
[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
output wanted :
[0, 0, 1, 0, 0, 1, 2, 3]
I tried to use enumerate but I fail, any suggestion ?
Edit : Every time I meet a new element in the list, I associate this new element with a number (start from 0 and +1 every new element) and if I recognize it later I put the same number, so [1,1] --> 0 because is the first element we met and [2,2] --> 1 etc...
Okay I found a solution :
One more thing before, my example is bad because I can have [1,2] in element of the list for input
the solution I found is
line = [[1, 1], [1, 1], [2, 2], [1, 1], [2, 1], [2, 2], [3, 3], [4, 4]]
p = []
line_not = []
k = 0
for i in range (len(line)):
if line[i] in line[:i]:
p.append(line_not[:k].index(line[i]))
else:
p.append(k)
line_not.append(line[i])
k+=1
the output is :
[0, 0, 1, 0, 2, 1, 3, 4]
If u have a better solution, tell me !

try to make a map, this works:
inp=[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = [0, 0, 1, 0, 0, 1, 2, 3]
mymap={inp[0][0]:0}
output = [0]
k_count=1
for i in inp[1:]:
if i[0] in mymap.keys():
output.append(mymap[i[0]])
else:
mymap[i[0]] = k_count
output.append(mymap[i[0]])
k_count+=1
and then output == [0, 0, 1, 0, 0, 1, 2, 3]

First build a dictionary that does the assocation of each unique element with a number:
>>> x = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
>>> d = {}
>>> for [i, _] in x:
... if i not in d:
... d[i] = len(d)
...
and then you can easily build your output list by doing lookups in that dictionary:
>>> [d[i] for [i, _] in x]
[0, 0, 1, 0, 0, 1, 2, 3]

this would work in your current example, but it is not a comprehensive solution. Without context its hard to understand what you are trying to achieve, so use with care:
import numpy as np
inp = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = np.array([i[0] for i in inp]) - 1
print(out) # result: [0 0 1 0 0 1 2 3]

Related

Get value of variable index in particular dimension

Say if i have a tensor that is
value = torch.tensor([
[[0, 0, 0], [1, 1, 1]],
[[2, 2, 2], [3, 3, 3]],
])
essentially with shape (2,2,3).
Now say if i have an index = [1, 0], which means I want to take:
# row 1 of [[0, 0, 0], [1, 1, 1]], giving me: [1, 1, 1]
# row 0 of [[2, 2, 2], [3, 3, 3]], giving me: [2, 2, 2]
So that the final output:
output = torch.tensor([[1, 1, 1], [2, 2, 2]])
is there a vectorized way to achieve this?
You can use advanced indexing.
I can't find a good pytorch document about this, but I believe it works as same as numpy, so here's the numpy's document about indexing.
import torch
value = torch.tensor([
[[0, 0, 0], [1, 1, 1]],
[[2, 2, 2], [3, 3, 3]],
])
index = [1, 0]
i = range(0,2)
result = value[i, index]
# same as result = value[i, index, :]
print(result)

Python 3 list of all possible cohesive combinations

Hi I'm trying to make a list of all possible cohesive combinations of another list, so from [0, 1, 2, 3] I'd like to get [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]. So far I've got this:
def expandArray(arr):
result = []
for x in range(0, len(arr)):
subArray = [arr[x]]
result.append(subArray)
for y in range(x + 1, len(arr)):
subArray.append(arr[y])
result.append(subArray)
return(result)
But this returns: [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [2, 3], [2, 3], [3]].
What am I doing wrong ?
subArray is a list that you modify in your for loop. When you append to it, you do not create a new list, but you modify it, and then put it in the list again, so will in the end get a result with several copies of the same list. Compare this code:
a = []
b = [5]
a.append(b)
b.append(1)
a.append(b)
print(a)
would output:
[[5, 1], [5, 1]]
Here is a way to have your desired output using list slicing:
def get_combs(iterable):
for k, _ in enumerate(iterable):
elm = k
while elm <= len(iterable):
data = iterable[k:elm]
elm += 1
if data:
yield data
combs = list(get_combs([0, 1, 2, 3]))
print(combs)
Output:
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

How to get this list of combinations?

I have two numbers, N and L (let's say 5 and 3).
How can I generate every possible list where the sum of the list is equal to N (5) and the length of every list is L (3)?
Example output (in this case):
[0, 0, 5]
[0, 1, 4]
[0, 2, 3]
[0, 3, 2]
...
[0, 5, 0]
...
[1, 4, 0]
...
[5, 0, 0]
I've checked out itertools and its combinations and permutations functions, but they don't seem right for the task.
You can create a recursive function to generate all possible permutations with the given conditions, and then filter to retain only the lists which sum to the desired value:
def list_results(a, b):
return [i for i in permutations(b) if sum(i) == a]
def permutations(d, current = []):
if len(current) == d:
yield current
else:
for i in range(10):
yield from permutations(d, current+[i])
print(list_results(5, 3))
Output:
[[0, 0, 5], [0, 1, 4], [0, 2, 3], [0, 3, 2], [0, 4, 1], [0, 5, 0], [1, 0, 4], [1, 1, 3], [1, 2, 2], [1, 3, 1], [1, 4, 0], [2, 0, 3], [2, 1, 2], [2, 2, 1], [2, 3, 0], [3, 0, 2], [3, 1, 1], [3, 2, 0], [4, 0, 1], [4, 1, 0], [5, 0, 0]]
Edit: a slightly faster would entail an additional check in the recursive function:
import time
def timeit(f):
def wrapper(*args, **kwargs):
c = time.time()
results = list(f(*args, **kwargs))
print("Result from function '{}' achieved in {}".format(f.__name__, abs(c-time.time())))
return results
return wrapper
#timeit
def outer_permutations():
def permutations1(d, b, current = []):
if len(current) == d:
yield current
else:
for i in range(10):
if len(current) < 2 or sum(current+[i]) == b:
yield from permutations1(d, b, current+[i])
yield from permutations1(3, 5)
#timeit
def list_results(a, b):
return [i for i in permutations(b) if sum(i) == a]
v = outer_permutations()
v1 = list_results(3, 5)
Output:
Result from function 'outer_permutations' achieved in 0.0006079673767089844
Result from function 'list_results' achieved in 0.09148788452148438
Note that the output from both functions is:
[[0, 0, 5], [0, 1, 4], [0, 2, 3], [0, 3, 2], [0, 4, 1], [0, 5, 0], [1, 0, 4], [1, 1, 3], [1, 2, 2], [1, 3, 1], [1, 4, 0], [2, 0, 3], [2, 1, 2], [2, 2, 1], [2, 3, 0], [3, 0, 2], [3, 1, 1], [3, 2, 0], [4, 0, 1], [4, 1, 0], [5, 0, 0]]

Removing a sublist from a list that meets a certain condition

I create all three-element permutations without mirroring, using itertools.product():
import itertools
list_1 = [list(i) for i in itertools.product(tuple(range(4)), repeat=3) if tuple(reversed(i)) >= tuple(i)]
Output:
[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 2, 3], [0, 3, 0], [0, 3, 1], [0, 3, 2], [0, 3, 3], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 1], [1, 3, 2], [1, 3, 3], [2, 0, 2], [2, 0, 3], [2, 1, 2], [2, 1, 3], [2, 2, 2], [2, 2, 3], [2, 3, 2], [2, 3, 3], [3, 0, 3], [3, 1, 3], [3, 2, 3], [3, 3, 3]]
How do I delete these sublisters from the list list_1, which have the same number of corresponding values and then leave only one of them?
For example, in sublists [1,1,2], [1,2,1] the number of given values is the same in all, that is, in each sub-list there are two 1 and one 2, that's why I consider the sublisters to be the same and that's why I want to leave only the first one, namely [1,1,2]. How can this be done?
I was thinking about counting the number of corresponding values in each sub-list and creating a list with the occurring feature regarding the amount of given values, and then checking each element from the list list_1 in the loop or the element with the given feature has not occurred before. But it seems to me to be very complicated.
Rather than using product from the itertools module, use combinations_with_replacement. That does what you want in one line without any massaging afterward:
list1 = [list(i) for i in combinations_with_replacement(range(4),3)]
The result of print(list1) after that is
[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 2, 2], [0, 2, 3], [0, 3, 3], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]]
Note that your conversion of the range object to a tuple is not necessary.
This might do the trick:
import itertools
def uniqifyList(list):
indexToReturn = []
sortedUniqueItems = []
for idx, value in enumerate(list):
# check if exists in unique_list or not
value.sort()
if value not in sortedUniqueItems:
sortedUniqueItems.append(value)
indexToReturn.append(idx)
return [list[i] for i in indexToReturn]
list1 = [list(i) for i in itertools.product(tuple(range(4)), repeat=3) if tuple(reversed(i)) >= tuple(i)]
print(list1)
list2 = uniqifyList(list1)
print(list2)
Which outputs:
[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 2, 2], [0, 2, 3], [0, 3, 3], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]]
You can sort each sublist and then extract unique sublists out as follows.
list_2 = map(sorted, list_1)
list_u = []
[list_u.append(x) for x in list_2 if x not in list_u]
Output:
list_u = [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 2, 2], [0, 2, 3], [0, 3, 3], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]]
Now, there are more efficient options than sorting each sublist, but I will leave that upto you.

Transposing a nxn Matrix in Python using only for/while loops

I wanted to know why the solution I have written doesn't work:
def transpose(sudoku):
n = len(sudoku)
l_tr = [0]*n
k = 0
tr_sudoku = [0]*n
while k < n:
tr_sudoku[k] = l_tr
k = k+1
i = 0
for i in range(len(sudoku)):
j = 0
for j in range(len(sudoku)):
tr_sudoku[i][j] = sudoku[j][i]
print j, i, tr_sudoku, sudoku[i][j]
print tr_sudoku
return tr_sudoku
correct = [[1,2,3],[2,3,1],[3,1,2]]
print transpose(correct)
It outputs the following incorrect solution:
0 0 [[1, 0, 0], [1, 0, 0], [1, 0, 0]] 1
1 0 [[1, 2, 0], [1, 2, 0], [1, 2, 0]] 2
2 0 [[1, 2, 3], [1, 2, 3], [1, 2, 3]] 3
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
0 1 [[2, 2, 3], [2, 2, 3], [2, 2, 3]] 2
1 1 [[2, 3, 3], [2, 3, 3], [2, 3, 3]] 3
2 1 [[2, 3, 1], [2, 3, 1], [2, 3, 1]] 1
[[2, 3, 1], [2, 3, 1], [2, 3, 1]]
0 2 [[3, 3, 1], [3, 3, 1], [3, 3, 1]] 3
1 2 [[3, 1, 1], [3, 1, 1], [3, 1, 1]] 1
2 2 [[3, 1, 2], [3, 1, 2], [3, 1, 2]] 2
[[3, 1, 2], [3, 1, 2], [3, 1, 2]]
[[3, 1, 2], [3, 1, 2], [3, 1, 2]]
Help would be appreciated! Thanks.
The ideal correct solution to:
correct = [[1,2,4],[2,3,4],[3,4,2]]
would be:
tr_correct = [[1,2,3],[2,3,4],[4,4,2]]
You can easily transpose with zip:
def transpose(sudoku):
return list(map(list, zip(*sudoku)))
Example output:
>>> correct = [[1,2,3],[2,3,1],[3,1,2]]
>>> transpose(correct)
[[1, 2, 3], [2, 3, 1], [3, 1, 2]]
The easiest "manual" way is to switch rows and columns:
def transpose_manually(sudoku):
output = sudoku[:] # new grid the same size
for r in range(len(sudoku)): # each row
for c in range(len(sudoku[0])): # each column
output[c][r] = sudoku[r][c] # switch
return output

Categories

Resources