-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpypicker.py
142 lines (111 loc) · 4.68 KB
/
pypicker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__version__ = 1.0
import argparse
import random
parser = argparse.ArgumentParser(
description='Randomly pick items from a list',
epilog='Created by Jason Bristol <[email protected]>')
parser.add_argument('n',
metavar='SAMPLE SIZE',
nargs='?',
type=int,
default=1,
help="number of items to pick (default: %(default)s)")
parser.add_argument('list',
metavar='SAMPLE GROUP',
nargs='*',
type=str,
default=[],
help="list of items to choose from.")
parser.add_argument('-i',
metavar='PATH',
type=argparse.FileType('r'),
help="input file of items to choose from")
parser.add_argument('-g',
metavar='INTEGER',
type=int,
default=1,
help="number of result groups to generate (default: %(default)s)")
parser.add_argument('-o',
metavar='PATH',
type=argparse.FileType('w'),
help="output file to write results to")
parser.add_argument('-j',
metavar='DELIMITER',
type=str,
help="join results using specified delimiter")
parser.add_argument('-v', '--verbose',
action='store_true',
help="verbose output")
parser.add_argument('-u', '--unique',
action='store_true',
help="force uniqueness across result groups")
parser.add_argument('--version',
action='version',
version='%(prog)s {version}'.format(version=__version__))
args = parser.parse_args()
class PyPickerException(Exception):
""" This is the base PyPicker error class """
pass
class BoundsException(PyPickerException):
""" This error occurs when the n argument is out of bounds """
def __init__(self, msg):
self.msg = str(msg)
class OutputException(PyPickerException):
""" This error occurs when the output file cannot be written to """
def __init__(self, msg):
self.msg = str(msg)
class ResultSetException(PyPickerException):
""" This error occurs when the requested result set is greater than the sample size """
def __init__(self, msg):
self.msg = str(msg)
def SimpleRandomSample(sample_set, sample_size):
"""
A simple random sample is a sample in which every member of the population has an equal chance of being chosen.
:param sample_set: set of values to select from
:param sample_size: number of values to select
:return: result sample
"""
return random.sample(sample_set, sample_size)
def pick(n, num_groups, sample_set, output_file, verbose, join, unique_groups):
"""
Validates and orchestrates result picks
:param n: number of values to pick
:param num_groups: number of samples to pick
:param sample_set: set of values to choose from
:param output_file: path to output file
:param verbose: set verbosity
:param join: join the result with a delimiter
:param unique_groups: set uniqueness
:return:
"""
resultString = [] # Array of result strings
sampleSize = [0, 0] # [<num_picked>, <num_total>]
if n not in range(0, len(sample_set) + 1):
raise BoundsException("n out of bounds, please select a number within 1 <= n <= total items")
sampleSize[1] = len(sample_set)
for i in range(0, num_groups):
results = SimpleRandomSample(sample_set, n)
sampleStr = (sampleSize[1] - sampleSize[0]) if unique_groups else sampleSize[1]
if unique_groups:
if (n * num_groups) > sampleSize[1]:
raise ResultSetException("Requested result set is larger than sample size")
else:
for result in results:
sample_set[:] = [x for x in sample_set if x != result]
if verbose:
resultString.append("Picking {} item(s) out of {}:".format(n, sampleStr))
resultString.append("\n".join(results) if join is None else "{}".format(join).join(results))
sampleSize[0] += n
if output_file == None:
print("\n\n".join(resultString))
else:
try:
output_file.write("\n\n".join(resultString))
except Exception as e:
raise OutputException(e)
if __name__ == "__main__":
sample_set = args.list if args.i is None else [line.strip() for line in args.i.readlines()]
random.shuffle(sample_set)
pick(args.n, args.g, sample_set, args.o, args.verbose, args.j, args.unique)