Related
I want to generate random result with weights based on the previous result.
I am generating random results with weights in the following manner
a = [1, 2, 3, 4, 5, 6]
results = random.choices(a, weights=(
(10, 20, 30, 30, 10, 6)), k=100)
print (results[0:100]
What I want to do is if results[n] = 1, the next result cannot be 6(i.e. it can be between 1 and 5).
I am new to this page and python. Any help would be useful
Using Kelly Bundy's suggestion from the comments:
a = [1, 2, 3, 4, 5, 6]
choices = random.choices(a, weights=(10, 20, 30, 30, 10, 6), k=100)
# print(choices)
for i, (prev, curr) in enumerate(zip(choices[:-1], choices[1:])):
if prev == 1 and curr == 6:
# print(f'Rerolled {i + 1}')
choices[i + 1] = random.choices(a, weights=(10, 20, 30, 30, 10, 0), k=1)[0]
print(choices)
Example Output:
[5, 4, 4, 1, 3, 4, 5, 6, 3, 4, 1, 2, 4, 2, 4, 3, 1, 3, 2, 3, 1, 2, 5, 4, 4, 3, 6, 4, 3, 4, 1, 5, 1, 3, 1, 3, 2, 1, 3, 4, 2, 4, 4, 1, 5, 2, 4, 4, 4, 6, 3, 3, 3, 2, 1, 4, 2, 2, 5, 4, 4, 2, 2, 4, 1, 3, 4, 4, 5, 4, 4, 4, 4, 3, 1, 4, 3, 4, 4, 4, 4, 4, 4, 2, 3, 5, 3, 2, 4, 4, 1, 2, 5, 6, 3, 4, 4, 6, 4, 3]
You could change the corresponding weight for 6 to 0 for the next choice if the previous choice was a 1:
a = [1, 2, 3, 4, 5, 6]
choices = []
k = 100
i = 0
previous_choice_1 = False
while i < k:
if previous_choice_1:
choice = random.choices(a, weights=(10, 20, 30, 30, 10, 0), k=1)[0]
else:
choice = random.choices(a, weights=(10, 20, 30, 30, 10, 6), k=1)[0]
choices.append(choice)
previous_choice_1 = choice == 1
i += 1
print(choices)
Example Output:
[6, 3, 3, 6, 2, 3, 3, 1, 2, 3, 6, 1, 2, 2, 6, 4, 3, 3, 2, 2, 1, 2, 3, 4, 4, 3, 2, 5, 4, 4, 3, 3, 4, 3, 3, 3, 1, 4, 5, 1, 2, 4, 4, 2, 4, 3, 4, 3, 6, 4, 1, 5, 3, 4, 4, 2, 4, 3, 4, 3, 3, 4, 3, 2, 2, 2, 3, 4, 3, 2, 1, 4, 4, 3, 3, 1, 3, 4, 5, 4, 4, 3, 1, 2, 2, 6, 3, 2, 3, 3, 4, 2, 1, 2, 4, 3, 3, 3, 1, 4]
I got this code
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = [0 for b in range(16)]
skipped = 0
for i in range(16):
if A[i] == A[i-1]:
skipped += 1
else:
B[i-skipped] = A[i]
print(B)
The output:
[1, 2, 3, 4, 5, 2, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0]
it eliminates the doubles. But if i got an array where doubles are at more random index it fails, like:
The Array#2:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 2, 2, 2, 7, 8, 8, 9]
The output#2
[1, 2, 3, 4, 5, 2, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0]
In the output#2 there is the value 2 at index 1 and index 5, but i just want to eliminate all the doubles.
Sum:
So basically my algorithm should copy the values from Array A to Array B and eliminate all doubles independent from their index.
EDIT: i have to put it in pseudocode so i cant use convert methods or functions like SET
You can use set to do it:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = set(A)
print(B)
This code returns a set. To convert set to list you can write some_list = list(B).
Another way to do what you need:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = []
for x in A:
if x not in B:
B.append(x)
print(B)
I start with a list of integers:
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
After a shuffle, I would like some elements (say 3, 4 and 5) to preserve their order of occurrence in A while the rest of the elements are free to be randomly shuffled. Something like:
Outcome #1:
A = [ 5, 2, 3, 1, 8, 4, 6, 7 ]
-or-
Outcome #2:
A = [ 7, 5, 6, 1, 3, 4, 8, 2 ]
-but not-
Outcome #3 (invalid outcome)
A = [7, 4, 6, 1, 3, 5, 8, 2]
Appreciate all suggestions!
Extract the elements you want to maintain relative ordering among, shuffle as normal, then glue the lists back together by randomly picking indexes for the "kept" elements to be inserted. All operations are linear if you use sets for speeding up in operations, which I didn't bother with. Ordering of the keep list matters.
>>> import random
>>> L = [1, 2, 5, 3, 4, 6, 7, 8]
>>> keep = [2, 3, 4]
>>> kept = [L[i] for i in keep][::-1]
>>> unkept = [x for i, x in enumerate(L) if i not in keep]
>>> random.shuffle(unkept)
>>> idxes = random.sample(list(range(len(L))), k=len(keep))
>>> result = [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
>>> result
[6, 5, 3, 8, 4, 1, 7, 2]
Random tests:
import random
def shuffle_with_fixed_order(L, keep):
kept = [L[i] for i in keep][::-1]
unkept = [x for i, x in enumerate(L) if i not in keep]
random.shuffle(unkept)
idxes = random.sample(list(range(len(L))), k=len(keep))
return [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
if __name__ == "__main__":
for _ in range(5000):
L = list(range(50))
random.shuffle(L)
keep = sorted(random.sample(L, k=20))
shuffled = shuffle_with_fixed_order(L, keep)
new_locs = [shuffled.index(L[i]) for i in keep]
assert all(x < y for x, y in zip(new_locs, new_locs[1:]))
This is one approach using random module
Ex:
import random
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
result = A[2:5]
del A[2:5]
while A:
l = len(A)
result.insert(random.randint(0, l), A.pop(random.randrange(l)))
print(result)
Demo
def rand_shfl(lst):
result = lst[2:5]
del lst[2:5]
while A:
l = len(A)
result.insert(random.randint(0, l), A.pop(random.randrange(l)))
return result
for _ in range(10):
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
print((rand_shfl(A)))
Output:
[1, 7, 6, 5, 8, 3, 4, 2]
[8, 1, 2, 7, 5, 3, 6, 4]
[8, 6, 7, 2, 1, 5, 3, 4]
[1, 7, 2, 8, 5, 3, 4, 6]
[6, 8, 7, 5, 1, 3, 4, 2]
[7, 2, 5, 6, 1, 3, 4, 8]
[1, 8, 5, 2, 3, 4, 6, 7]
[5, 7, 1, 6, 3, 8, 4, 2]
[1, 5, 7, 3, 2, 4, 8, 6]
[8, 2, 7, 6, 5, 3, 4, 1]
Probably below will work for you
import random
lst=[1, 2, 5, 3, 4, 6, 7, 8]
s_lst = {5:0,3:0,4:0}
idx_lst = [random.randint(0, len(lst)) for i in range(len(s_lst))]
idx_lst.sort()
for i, s in enumerate(s_lst.keys()):
s_lst[s] = idx_lst[i]
lst.remove(s)
random.shuffle(lst)
for k, v in s_lst.items():
lst.insert(v, k)
print(lst)
I want to go from one array A of 10 elements to the array B of 100 elements.
Each element of B from 0 to 9 is equal to the element 0 of A
Each element of B from 10 to 19 is equal to the element 1 of A
....
Each element of B from 90 to 99 is equal to the element 9 of A
I did the following code but it does not work
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A = np.asarray(a)
b = []
for i in range(len(A)*10):
b.append(0)
B = np.asarray(b)
for i in range(len(A)):
for j in range(9):
B[j]=A[i]
Expected result:
B [ 0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2
...,
9,9,9,9,9,9,9,9,9,9 ]
You are saving values only in first 9 list elements. You have to 'scale' it by adding i*10 to index.
import numpy as np
a=[0, 1, 2, 3, 4, 5, 6, 7]
A = np.asarray(a)
b = []
for i in range(len(A)**2):
b.append(0)
B = np.asarray(b)
for i in range(len(A)):
for j in range(len(A)):
B[j + i*len(A)]=A[i]
print(B)
This works for me:
>>> a = [1,2,3]
>>> [ x for i in a for x in [i]*3]
[1, 1, 1, 2, 2, 2, 3, 3, 3]
>>>
You may replace 3 with 10 or whatever you like.
Answering the question from Jacob:
>>> [[a]*10 for a in A]
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]
You should avoid loops with numpy whenever possible. It kind of defeats the point. Here you can just use repeat():
import numpy as np
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A = np.asarray(a)
B = A.repeat(10)
B:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9])
If want the a nested list, just reshape:
B = A.repeat(10).reshape(-1, 10)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]])
You can use numpy and specify how many iterations of each element you want:
import numpy as np
A = [1,2,3,4]
B = [np.full(10, a) for a in A]
print(B)
Or if you prefer to not use numpy, instead use:
A = [1,2,3,4]
B = [[a]*10 for a in A]
print(B)
Giving you the wanted list B
Try this:
a = [*range(10)]
b = []
for i in range(10):
b.extend([a[i]* 10])
B = np.asarray(b)
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = []
for x in a:
b += [x] * 10
print b
This answer is better, idea from lenik
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [x for x in a for i in range(10)]
print b
Answer in a single line: print([item for sublist in [[i]*10 for i in range(1,10)] for item in sublist])
If a were a generic list and not an ordered sequence
In [20]: a = [1, 'a', 3.14159, False, {1:2, 3:4}]
you could do as follows
In [21]: [_ for _ in (zip(*(a for _ in a))) for _ in _]
Out[21]:
[1,
1,
1,
1,
1,
'a',
'a',
'a',
'a',
'a',
3.14159,
3.14159,
3.14159,
3.14159,
3.14159,
False,
False,
False,
False,
False,
{1: 2, 3: 4},
{1: 2, 3: 4},
{1: 2, 3: 4},
{1: 2, 3: 4},
{1: 2, 3: 4}]
list1=[]
list2=[]
for i in range (0,10,1):
list1.append(i)
print(list1)
for i in range (0,10,1):
for j in range (0,10,1):
j=i
list2.append(j)
print(list2)
I have a list of integers(or could be even strings), which I would like to sort by the frequency of occurrences in Python, for instance:
a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
Here the element 5 appears 4 times in the list, 4 appears 3 times. So the output sorted list would be :
result = [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
I tried using a.count(), but it gives the number of occurrence of the element.
I would like to sort it. Any idea how to do it ?
Thanks
from collections import Counter
print [item for items, c in Counter(a).most_common() for item in [items] * c]
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or even better (efficient) implementation
from collections import Counter
from itertools import repeat, chain
print list(chain.from_iterable(repeat(i, c) for i,c in Counter(a).most_common()))
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or
from collections import Counter
print sorted(a, key=Counter(a).get, reverse=True)
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
If you prefer in-place sort
a.sort(key=Counter(a).get, reverse=True)
Using Python 3.3 and the built in sorted function, with the count as the key:
>>> a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
>>> sorted(a,key=a.count)
[2, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
>>> sorted(a,key=a.count,reverse=True)
[5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
In [15]: a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
In [16]: counts = collections.Counter(a)
In [17]: list(itertools.chain.from_iterable([[k for _ in range(counts[k])] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
Out[17]: [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Alternatively:
answer = []
for k in sorted(counts, key=counts.__getitem__, reverse=True):
answer.extend([k for _ in range(counts[k])])
Of course, [k for _ in range(counts[k])] can be replaced with [k]*counts[k].
So line 17 becomes
list(itertools.chain.from_iterable([[k]*counts[k] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
If you happen to be using numpy already, or if using it is an option, here's another alternative:
In [309]: import numpy as np
In [310]: a = [1, 2, 3, 3, 1, 3, 5, 4, 4, 4, 5, 5, 5]
In [311]: vals, counts = np.unique(a, return_counts=True)
In [312]: order = np.argsort(counts)[::-1]
In [313]: np.repeat(vals[order], counts[order])
Out[313]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
That result is a numpy array. If you want to end up with a Python list, call the array's tolist() method:
In [314]: np.repeat(vals[order], counts[order]).tolist()
Out[314]: [5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2]
Not interesting way...
a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
from collections import Counter
result = []
for v, times in sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True):
result += [v] * times
One liner:
reduce(lambda a, b: a + [b[0]] * b[1], sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True), [])
Occurrence in array and within a sets of equal size:
rev=True
arr = [6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7 ,8 ,8, 8, 2]
print arr
arr.sort(reverse=rev)
ARR = {}
for n in arr:
if n not in ARR:
ARR[n] = 0
ARR[n] += 1
arr=[]
for k,v in sorted(ARR.iteritems(), key=lambda (k,v): (v,k), reverse=rev):
arr.extend([k]*v)
print arr
Results:
[6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7, 8, 8, 8, 2]
[2, 2, 2, 2, 2, 6, 6, 6, 6, 5, 5, 5, 5, 9, 9, 9, 8, 8, 8, 4, 4, 7, 3, 1]
Dart Solution
String sortedString = '';
Map map = {};
for (int i = 0; i < s.length; i++) {
map[s[i]] = (map[s[i]] ?? 0) + 1;
// OR
// map.containsKey(s[i])
// ? map.update(s[i], (value) => ++value)
// : map.addAll({s[i]: 1});
}
var sortedByValueMap = Map.fromEntries(
map.entries.toList()..sort((e1, e2) => e1.value.compareTo(e2.value)));
sortedByValueMap.forEach((key, value) {
sortedString += key * value;
});
return sortedString.split('').reversed. Join();