I just started programming in Python, and I can't figure out how to make the index change if I want the values in the list to be the same. What I want is for the index to change, so it will print 0, 1, 2, but all I get is 0, 0, 0. I tried to change the values of the list so that they were different, and then I got the output I wanted. But I don't understand why it matters what kind of values I use, why would the index care about what is in the list?
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
something = justTesting.index(item)
print (something)
I'm using python 3.6.1 if that mattters
Because each list (designated 'item' in your loop) is [0, 0] this means the line:
something = justTesting.index(item)
will look for the first instance of the list [0, 0] in the list for each 'item' during the iteration. As every item in the list is [0, 0] the first instance is at position 0.
I have prepared an alternative example to illustrate the point
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
print(item)
something = justTesting.index(item)
print(something)
This results in the following:
[1, 2]
0
[3, 4]
1
[5, 6]
2
It's because your list only contains [0, 0]!
So basically, if we replace all the variables with their values, we get:
justTesting = [[0, 0], [0, 0], [0, 0]]
And using .index(item) will return the first occurrence of item if any. Since item is always [0, 0] and it first appears at justTesting[0], you will always get 0! Try changing up the values in each list and try again. For example, this works:
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for item in b:
print(b.index(item))
Which returns:
0, 1, 2, 3, 4, 5, 6, 7, 8
if the results were on a single line.
Try it here!
Read the documentation: the default for index is to identify the first occurence. You need to use the start parameter as well, updating as you go: search only the list after the most recent find.
something = justTesting.index(item, something+1)
That's because you are iterating over a list of lists.
Every item is actually a list, and you are executing list.index() method which returns the index of the element in the list.
This is a little tricky. Since you actually have 3 lists, of [0, 0] their values will be the same when testing for equality:
>>> a = 0
>>> b = 0
>>> c = 0
>>> d = 0
>>> ab = [a, b]
>>> cd = [c, d]
>>>
>>> ab is cd
False
>>> ab == cd
True
>>>
Now when you run list.index(obj) you are looking for the 1st index that matches the object. Your code actually runs list.index([0, 0]) 3 times and returns the first match, which is at index 0.
Put different values inside a, b, c lists and it would work as you expect.
Your code:
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
justTesting = [[a, b], [c, d], [e, f]]
for item in justTesting:
something = justTesting.index(item)
print (something)
is equivalent to:
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
ab = [a, b]
cd = [c, d]
ef = [e, f]
justTesting = [ab, cd, ef]
# Note that ab == cd is True and cd == ef is True
# so all elements of justTesting are identical.
#
# for item in justTesting:
# something = justTesting.index(item)
# print (something)
#
# is essentially equivalent to:
item = justTesting[0] # = ab = [0, 0]
something = justTesting.index(item) # = 0 First occurrence of [0, 0] in justTesting
# is **always** at index 0
item = justTesting[1] # = cd = [0, 0]
something = justTesting.index(item) # = 0
item = justTesting[2] # = ef = [0, 0]
something = justTesting.index(item) # = 0
justTesting does not change as you iterate and the first position in justTesting at which [0,0] is found is always 0.
But I don't understand why it matters what kind of values I use, why would the index care about what is in the list?
Possibly what is confusing you is the fact that index() does not search for occurrences of the item "in abstract" but it looks at the values of items in a list and compares those values with a given value of item. That is,
[ab, cd, ef].index(cd)
is equivalent to
[[0,0],[0,0],[0,0].index([0,0])
and the first occurrence of [0,0] value (!!!) is at 0 index of the list for your specific values for a, b, c, d, e, and f.
Related
So I want to cycle through variables A through J and assign numbers 0 through 9
but in a way that it goes through all possible combinations (yeah it's a lot)
the code that I came up with is as follows
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
g = 0
h = 0
i = 0
j = 0
checkedValues = [False, False, False, False, False, False, False, False, False, False]
firstCycle = True
values = [a, b, c, d, e, f, g, h, i, j]
running = True
i = 0
j = 0
while running == True:
if not checkedValues[i]:
for temp in range(10):
j = temp + i
if j < 10:
values[temp] = j
else:
j -= 10
values[temp] = j
i += 1
print(values)
if i == 9:
i = 0
tempvar = values.pop(0)
values.append(tempvar)
if values == [a, b, c, d, e, f, g, h, i, j]:
if firstCycle:
firstCycle = False
else:
break
Question is if there are ways to do this faster and more efficiently.
edit: this code, kinda, works. Besides optimization problems, I also run into the issue that I want the variables to be seen separately from the list/array that they're in. Only putting them in the list/array in the first place so that I can easily cycle through them to change the variables
It would be helpful if you provide some context to your question. But anyways I hope I got what you want to achieve - here would be my suggestion:
import itertools
min = 0
max = 9
possible_choices = [i for i in range(min, max + 1)]
all_combinations = list(itertools.permutations(possible_choices))
print(all_combinations)
for combination in all_combinations:
# cycle through the results and do whatever you need to do
print(combination)
Luckily for your PC, I have completely misunderstood the question at first, the problem can be solved as following:
max_val = 10
values = list(range(max_val))
result = [[(i + j) % max_val for i in values] for j in values]
I have used a double list comprehension to make it shorter. The code is somewhat equivalent to:
results = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
for j in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
results[i, j] = (i + j) % 10
Just for reference, I have previously assumed that you want to have a series of 10-long lists of all combinations of numbers from 0 to 10, which should be something like 10'000'000'000 elements long, hence my worry and use of itertools.product.
Edit: It looks like you indeed want to get all combinations, in which case the answer by Tetrick25 looks reasonable.
I have a dictionary dico like this :
id_OS (keys) : List of pages(values)
0 : [A, B]
1 : [C, D, E]
2 : [F, B]
3 : [G, A, B]
I would like to change it to this form
id_OS : List of index id_pages
0 : [0, 1]
1 : [2, 3, 4]
2 : [5, 1]
3 : [6, 0, 1]
I try this code, but i didnt got the correct index of values :
dico = dict(zip(range(len(dico)), zip(range(len(dico.values())))))
Any idea please to do it
Thanks
This should work:
letters = {0: ['A', 'B'], 1: ['C', 'Z']}
for key in letters:
new_list = []
for i in letters[key]:
i = i.lower()
new_list.append(ord(i) - 97)
letters[key] = new_list
I subtracted 97 instead of 96 (The reason why 96 is subtracted is well explained in this post: Convert alphabet letters to number in Python) because it seems like you want everything to be shifted so that A is 0 not 1 like it would usually be.
Output:
{0: [0, 1], 1: [2, 25]}
through your previous question I see that you could simplefy your task. I would change data['PageId'] type into categories and passed categories codes to the dictionary. Something like this:
data['codes'] = data['PageId'].astype('category').cat.codes
then change this line in your code:
dico[tup].append(row['PageId'])
into this:
dico[tup].append(row['codes'])
I have a matrix filled with 0 values and I want to add randomly a 1 value into a and a+1 position. Then I want to use b and b+1 for the next row.. and so on.
How can I do it?
w, h = 10, 3
Matrix = [[0 for x in range(w)] for y in range(h)]
a = random.randint(0,9)
b = random.randint(0,9)
c = random.randint(0,9)
print(a, b, c)
EXAMPLE:
a = 5 b = 2 c = 1
0000011000
0011000000
0110000000
You should reduce the randint range to 8 (more generically w-2), or alternatively use randrange so you don't cross the edge of the row with the +1.
Then just loop on each row, generate the number and change that row using the number as an index:
import random
w, h = 10, 3
matrix = [[0 for x in range(w)] for y in range(h)]
for row in matrix:
i = random.randrange(w-1)
print(i)
row[i:i+2] = [1, 1]
print(*matrix, sep='\n')
Will give:
0
8
2
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0]
In matrices in Python, you can access the row with [] and the columns with [][],
So if you want the third item in the second row, it would be [1][2] note we're starting from 0.
Getting back to your question, it would look something like this,
Matrix[0][a] = 1
Matrix[0][a + 1] = 1
And so on for the b, c but you could also use a loop.
random = [a, b, c]
for row in range(h):
Matrix[row][random[row]] = 1
Matrix[row][random[row] + 1] = 1
Basically what we're doing in this loop, is for each row in the matrix, which in your code is defined by h and we will look at the first row and define at the index of the random value 'a' and update it to 1.
then we'll go to 'a + 1' in the same row and also update it to 1.
And then for the next row, we'll take b and do the same thing.
Note: this would raise an error if a, b or c are 9 because as soon as you increase it by 1 you will be out the boundaries of the list which is 0 to 9
I have two lists of element
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
and I am trying to uniquely match the element from a to b, my expected result is like this:
1: 3
2: 1
3: 2
So I tried to construct an assignment matrix and then use scipy.linear_sum_assignment
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
total_true = np.unique(a)
total_pred = np.unique(b)
matrix = np.zeros(shape=(len(total_pred),
len(total_true)
)
)
for n, i in enumerate(total_true):
for m, j in enumerate(total_pred):
matrix[n, m] = sum(1 for item in b if item==(i))
I expected the matrix to be:
1 2 3
1 0 2 0
2 0 0 2
3 6 0 0
But the output is:
[[2. 2. 2.]
[2. 2. 2.]
[6. 6. 6.]]
What mistake did I made in here? Thank you very much
You don't even need to process this by Pandas. try to use zip and dict:
In [42]: a = [1,2,3,2,3,1,1,1,1,1]
...: b = [3,1,2,1,2,3,3,3,3,3]
...:
In [43]: c =zip(a,b)
In [44]: dict(c)
Out[44]: {1: 3, 2: 1, 3: 2}
UPDATE as OP said, if we need to store all the value with the same key, we can use defaultdict:
In [58]: from collections import defaultdict
In [59]: d = defaultdict(list)
In [60]: for k,v in c:
...: d[k].append(v)
...:
In [61]: d
Out[61]: defaultdict(list, {1: [3, 3, 3, 3, 3, 3], 2: [1, 1], 3: [2, 2]})
This row:
matrix[n, m] = sum(1 for item in b if item==(i))
counts the occurrences of i in b and saves the result to matrix[n, m]. Each cell of the matrix will contain either the number of 1's in b (i.e. 2) or the number of 2's in b (i.e. 2) or the number of 3's in b (i.e. 6). Notice that this value is completely independent of j, which means that the values in one row will always be the same.
In order to take j into consideration, try to replace the row with:
matrix[n, m] = sum(1 for x, y in zip(a, b) if (x, y) == (j, i))
In case your expected output, since how we specify the matrix as a(i, j) with i is the index of the row, and j is the index of the col. Looking at a(3,1) in your matrix, the result is 6, which means (3,1) combination matches 6 times, with 3 is from b and 1 is from a. We can find all the matches from 2 list.
matches = [tuple([x, y]) for x,y in zip(b, a)]
Then we can find how many matches there are of a specific combination, for example a(3, 1).
result = matches.count((3,1))
Assume I have two arrays, the first one containing int data, the second one containing positions
a = [11, 22, 44, 55]
b = [0, 1, 10, 11]
i.e. I want a[i] to be be moved to position b[i] for all i. If I haven't specified a position, then insert a -1
i.e
sorted_a = [11, 22,-1,-1,-1,-1,-1,-1,-1,-1, 44, 55]
^ ^ ^ ^
0 1 10 11
Another example:
a = [int1, int2, int3]
b = [5, 3, 1]
sorted_a = [-1, int3, -1, int2, -1, int1]
Here's what I've tried:
def sort_array_by_second(a, b):
sorted = []
for e1 in a:
sorted.appendAt(b[e1])
return sorted
Which I've obviously messed up.
Something like this:
res = [-1]*(max(b)+1) # create a list of required size with only -1's
for i, v in zip(b, a):
res[i] = v
The idea behind the algorithm:
Create the resulting list with a size capable of holding up to the largest index in b
Populate this list with -1
Iterate through b elements
Set elements in res[b[i]] with its proper value a[i]
This will leave the resulting list with -1 in every position other than the indexes contained in b, which will have their corresponding value of a.
I would use a custom key function as an argument to sort. This will sort the values according to the corresponding value in the other list:
to_be_sorted = ['int1', 'int2', 'int3', 'int4', 'int5']
sort_keys = [4, 5, 1, 2, 3]
sort_key_dict = dict(zip(to_be_sorted, sort_keys))
to_be_sorted.sort(key = lambda x: sort_key_dict[x])
This has the benefit of not counting on the values in sort_keys to be valid integer indexes, which is not a very stable thing to bank on.
>>> a = ["int1", "int2", "int3", "int4", "int5"]
>>> b = [4, 5, 1, 2, 3]
>>> sorted(a, key=lambda x, it=iter(sorted(b)): b.index(next(it)))
['int4', 'int5', 'int1', 'int2', 'int3']
Paulo Bu answer is the best pythonic way. If you want to stick with a function like yours:
def sort_array_by_second(a, b):
sorted = []
for n in b:
sorted.append(a[n-1])
return sorted
will do the trick.
Sorts A by the values of B:
A = ['int1', 'int2', 'int3', 'int4', 'int5']
B = [4, 5, 1, 2, 3]
from operator import itemgetter
C = [a for a, b in sorted(zip(A, B), key = itemgetter(1))]
print C
Output
['int3', 'int4', 'int5', 'int1', 'int2']
a = [11, 22, 44, 55] # values
b = [0, 1, 10, 11] # indexes to sort by
sorted_a = [-1] * (max(b) + 1)
for index, value in zip(b, a):
sorted_a[index] = value
print(sorted_a)
# -> [11, 22, -1, -1, -1, -1, -1, -1, -1, -1, 44, 55]