list = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
I would like to have a loop that randomly selects only ONE item from the indexes of the list for all 3 of them. So the loop would start and pick 3, then picks 7 and then picks 9, for example. And then the loop stops, doesn't continue on picking items again. I only want 3 repetitions
I have managed to do this
(with:
for i in list:
item = list[0].pop((random.choice(list)[0])))
but it doesn't do it only once, but it goes through all of the items (choosing the first one) of the first index, then moves to the second one and so on.
Any help is appreciated!
You seem to be indexing the list on 0 in each iteration, which will only give you random values from the first inner list. Use random.choice iterating over the list, or use map:
list(map(random.choice, my_list))
# [3, 8, 11]
Equivalently:
[random.choice(i) for i in my_list]
Based on the comments, if you want to remove the item you've randomly selected from the list, use instead:
[i.pop(random.randint(0,len(i))) for i in my_list]
# [4, 6, 9]
print(my_list)
# [[1, 2, 3], [5, 7, 8], [10, 11, 12]]
This is my code:
print("before random sample",pos)
pos = random.sample(pos, len(pos))
print("after random sample", pos)
test = [i.pop(random.randint(0,len(i))) for i in pos]```
This is the output:
#before random sample [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]
#after random sample [[6, 7, 8, 9, 10], [1, 2, 3, 4, 5], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]
#.......
#test = [i.pop(random.randint(0,len(i))) for i in pos]
#IndexError: pop index out of range
Related
I have tried two methods of creating groups of numbers and then dividing those groups into smaller groups of sequential numbers and selecting one.
The first method used lists, but they wouldn't divide the groups correctly.
# This program prints the wrong number of elements.
# I need the correct number of elements, and I want the list to
# deal with floats.
begin = 1
end = 22
num_groop = 2
num_in_groop = (begin + end) // num_groop
lis = []
# loop iterates through index making list from beginning to end
end = num_in_groop
for _ in np.arange(num_groop):
lis.append(list(np.arange(begin, end+1)))
begin += num_in_groop
end += num_in_groop
print('lis', lis,)
# a function to choose one group from the lis and print it
x_1 = lis[0]
x_2 = lis[1]
inp = input('Choose group 1 or 2 by entering 1 or 2\n')
intinp = int(inp)
def choosefunc():
if intinp == 1:
del x_2[:]
print('You chose group x_1 = ',x_1[:])
elif intinp == 2:
del x_1[:]
print('You chose group x_2 = ',x_2[:])
choosefunc()
print('lis is now', lis)
The problem with this is that when it's repeated to narrow down the groups, it divides only using integers. Though the original max number was 22, after repeating this twice, it produces the wrong number of lists. To be correct maths, it should be this:
The first division of the list into an even number is fine:
[[1,2,3,4,5,6,7,8,9,10,11], [12,13,14,15,16,17,18,19,20,21,22]].
Then when choosing one of these groups, choose the first, and divide by two again that's where the maths doesn't work. It should be this:
lis [[1, 2, 3, 4, 5, 5.5], [5.6, 7, 8, 9, 10, 11]]
But because it doesn't seem to handle floats, it is this:
lis [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]].
That's not correct maths. 22/2 = 11, and 11/2 = 5.5.
I want the lists to be of equal size.
# ---------------------------------------------------
When I try to solve the problem using lists, by using numpy arrays, I get an error that stops me from continuing.
# I tried to solve this problem using array but getting an error.
# TypeError: 'tuple' object cannot be interpreted as an integer.
import numpy as np
begin = 1
end = 22
num_groop = 2
num_in_groop = (begin + end) // num_groop
lis = np.array([])
print('lis is now', lis) # prints the new value for lis
end = num_in_groop
for _ in np.arange(num_groop):
print('line20, lis now', lis)
lis(np.arange(range((begin, end+1)))) #error
begin += num_in_groop
end += num_in_groop
print('lis', lis)
If [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]] is an acceptable split, then
def subdivide_list(a):
midpoint = len(a) // 2
return a[:midpoint], a[midpoint:]
lists = [list(range(1, 12))]
for x in range(3):
print(x, lists)
new_lists = []
for a in lists:
new_lists.extend(subdivide_list(a))
lists = new_lists
does what you want:
0 [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
1 [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
2 [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
EDIT
This also works for [list(range(1, 23))] (print adjusted to show the lengths of the lists):
0 [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]] [22]
1 [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]] [11, 11]
2 [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22]] [5, 6, 5, 6]
I have an algorithm problem to solve.
Description: I have a python dictionary that contains following
modules = {"auth_provider_1": [3, 4, 17, 19],
"auth_provider_2": [1, 6, 8, 10, 13, 14, 16, 18],
"auth_provider_3": [0, 7, 11, 12, 15],
"auth_provider_4": [2, 5, 9],
"cont_provider_1": [4, 14],
"cont_provider_2": [8, 9, 13, 15, 16, 17],
"cont_provider_3": [2, 3, 5, 10, 11, 18],
"cont_provider_4": [0, 1, 6, 7, 12, 19]}
There are two types of modules, auth_provider, and cont_provider.
Each one has 4 different providers. For example, we have 4 auth_providers; auth_provider_1, auth_provider_2, auth_provider_3 and auth_provider_4.
Each provider has a list that contains which user is using that provider.
each user is using only one auth provider and only one cont provider.
For example;
user 3 is using auth_provider_1 and cont_provider_3
user 1 is using auth_provider_2 and cont_provider_4.. and so on.
Problem: We want to check all providers with a minimum of a user group. For example, if we want to check what providers are users 0,2,4,8 using we will be checking all providers available. Same way with the users 0,2,4,16 and 0,2,4,13...etc
What I tried: Making a list from provider names sorted by their list length. For example;
sorted_list = ['cont_provider_1', 'auth_provider_4', 'auth_provider_1', 'auth_provider_3', 'cont_provider_2', 'cont_provider_3', 'cont_provider_4', 'auth_provider_2']
Iterating this sorted list, searching each element of its list in the modules dictionary and when it's found in a list I removed the key(provider_name) of that list from the sorted list.
For example from a sorted list, the first element is cont_provider_1 which has the smallest list length (it has only 4 and 14), I wanted to start from the smallest one because I thought it would make more sense. Then I search cont_provider_1 in the modules dictionary.
But when I find the 4 and auth_provider_1 and cont_provider_1 somehow iteration stuck somewhere and gives me this answer
sorted_list_after_iteration_is_over = ['auth_provider_4']
min_users = [4, 14, 0, 7, 11, 12, 15]
Question: What would be the best algorithm for this problem? Am I on the right track? Where I am doing wrong? Any suggestions or help?
here is my whole code
modules = {"auth_provider_1": [3, 4, 17, 19],
"auth_provider_2": [1, 6, 8, 10, 13, 14, 16, 18],
"auth_provider_3": [0, 7, 11, 12, 15],
"auth_provider_4": [2, 5, 9],
"cont_provider_1": [4, 14],
"cont_provider_2": [8, 9, 13, 15, 16, 17],
"cont_provider_3": [2, 3, 5, 10, 11, 18],
"cont_provider_4": [0, 1, 6, 7, 12, 19]}
providers_sorted_list = sorted(modules, key = lambda key: len(modules[key]))
# ['cont_provider_1', 'auth_provider_4', 'auth_provider_1', 'auth_provider_3', 'cont_provider_2', 'cont_provider_3', 'cont_provider_4', 'auth_provider_2']
test_users = []
for provider in providers_sorted_list:
search_list = modules[provider]
for user in search_list:
for key, val in modules.items():
if user in val:
if not user in test_users:
test_users.append(user)
if key in providers_sorted_list:
providers_sorted_list.remove(key)
print(providers_sorted_list)
print(test_users)
The problem is I'm trying to compare nested list and list without the same value or element ?
lst3 = [1, 6, 7, 10, 13, 28]
lst4 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
lst5 = [list(filter(lambda x: x not in lst3, sublist)) for sublist in lst4]
which returns:
[[17, 18, 21, 32], [11, 14], [5, 8, 15, 16]]
but I would like to get the number that don't match from l3. Here an example:
[[1,6,7,10,28],[1,6,10],[1,7,13,28]]
I would like the results to be:
[[1,6,7,10,28],[1,6,10],[1,7,13,28]]
In your example you are comparing each element in each sublist with lst3.
lst5 = [list(filter(lambda x: x not in lst3, sublist)) for sublist in lst4]
Problem is that you are asking whether each x from sublist is not in lst3 which is going to give you the remaining results from the sublist. You may want to do it the other way around.
lst5 = [list(filter(lambda x: x not in sublist, lst3)) for sublist in lst4]
Not only does it give you the answers you want but I even noticed you made a mistake in your expected results:
[[1, 6, 7, 10, 28], [1, 6, 10], [7, 10, 13, 28]]
Compared to yours:
[[1, 6, 7, 10, 28], [1, 6, 10], [1, 7, 13, 28]]
(See the last nested array)
Online example:
https://onlinegdb.com/Hy8K8GPSB
Rather than using things like filter and lambda, you could more readably just use a list comprehension:
lst5 = [[x for x in lst3 if not x in sublist] for sublist in lst4]
Which is
[[1, 6, 7, 10, 28], [1, 6, 10], [7, 10, 13, 28]]
This differs slightly from what you gave as your expected output, but I think that you made a typographical error in the third sublist of that expected output.
I would take John Coleman's answer but tweak the word order for readability.
lst5 = [[x for x in lst3 if x not in sublist] for sublist in lst4]
I have two list that are two dimensional list with at least 100 rows. I would like to match c1 to c2 or vice versa. But the real problem is instead of typing in row by row from c1 to match c2. Is there a faster way to loop through all the rows from c1 to match all the rows from c2 ?
I tried c1[0] and c1[1] and c1[2]. This method will work but i would have to do alot of typing row by row. This will be to much typing especially if its alot of rows?
Here i have two list that are two dimensional list.
c1 = [[2, 6, 7],[2,4,6],[3,6,8]].....
c2 = [[13, 17, 18], [7, 11, 13], [5, 6, 8]].......
[list(filter(lambda x: x in c3, sublist)) for sublist in c2].
I need to compare every item in a very long list (12471 items) to every other item in the same list. Below is my list:
[array([3, 4, 5])
array([ 6, 8, 10])
array([ 9, 12, 15])
array([12, 16, 20])
array([15, 20, 25])
...] #12471 items long
I need to compare the second item of each array to the first item of every other array to see if they're equal. And preferably, in a very efficient way. Is there a simple and efficient way to do this in Python 2.x?
I worked up a very crude method here, but it is terribly slow:
ls=len(myList) #12471
l=ls
k=0
for i in myList:
k+=1
while l>=0:
l-=1
if i[1]==myList[l][0]:
#Do stuff
l=ls
While this is still theoretically N^2 time (worst case), it should make things a bit better:
import collections
inval = [[3, 4, 5],
[ 6, 8, 10],
[ 9, 12, 15],
[ 12, 14, 15],
[12, 16, 20],
[ 6, 6, 10],
[ 8, 8, 10],
[15, 20, 25]]
by_first = collections.defaultdict(list)
by_second = collections.defaultdict(list)
for item in inval:
by_first[item[0]].append(item)
by_second[item[1]].append(item)
for k, vals in by_first.items():
if k in by_second:
print "by first:", vals, "by second:", by_second[k]
Output of my simple, short case:
by first: [[6, 8, 10], [6, 6, 10]] by second: [[6, 6, 10]]
by first: [[8, 8, 10]] by second: [[6, 8, 10], [8, 8, 10]]
by first: [[12, 14, 15], [12, 16, 20]] by second: [[9, 12, 15]]
Though this DOES NOT handle duplicates.
We can do this in O(N) with an assumption that python dict takes O(1) time for insert and lookup.
In the first scan, we create a map storing first number and row index by scanning the full list
In the second scan, we find if map from first scan contains second element of each row. If map contains then value of map gives us the list of row indices that match the required criterion.
myList = [[3, 4, 5], [ 6, 8, 10], [ 9, 12, 15], [12, 16, 20], [15, 20, 25]]
first_column = dict()
for idx, list in enumerate(myList):
if list[0] in first_column:
first_column[list[0]].append(idx)
else:
first_column[list[0]] = [idx]
for idx, list in enumerate(myList):
if list[1] in first_column:
print ('rows matching for element {} from row {} are {}'.format(list[1], idx, first_column[list[1]]))
This is a bit of a python 101 question, but I can't think of a pythonic way to enumerate a list of breakpoints to all integers between those breakpoints.
Say I have:
breaks = [4, 7, 13, 15, 18]
and I want
enumerated = [[4,5,6],[7,8,9,10,11,12],[13,14],[15,16,17],[18]]
(My actual use case involves breakpoints that are years; I want all years in each range).
I could loop through breaks with a counter, create a range for each interval and store it in a list, but I suspect there is a simple one-liner for this sort of enumeration. Efficiency is a concern since I am working with millions of records.
You can use zip
>>> enumerated = [range(start, end) for start,end in zip(breaks, breaks[1:])] + [[breaks[-1]]]
>>> enumerated
[[4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14], [15, 16, 17], [18]]
Using a zipping of a list with itself in an offset of one (zip(breaks, breaks[1:]) is a known "trick" to get all pairs. This drops the last one so I added it manually.
you can create a generator, it will be memory efficient:
def f(b):
if not b:
raise StopIteration
x = b[0]
for y in b[1:]:
yield xrange(x, y)
x = y
yield [y]
print list(f(breaks))
You can use a simple list comprehension and range()
breaks = [4, 7, 13, 15, 18]
new = [range(breaks[i],breaks[i+1]) for i in xrange(len(breaks)-1)]+[[breaks[-1]]]
print new
[[4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14], [15, 16, 17]]