Passing integer lists to python

36,041

Solution 1

You can pass them as strings than convert to lists. You can use argparse or optparse.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--l1', type=str)
parser.add_argument('--l2', type=str)
args = parser.parse_args()
l1_list = args.l1.split(',') # ['1','2','3','4']

Example: python prog.py --l1=1,2,3,4

Also,as a line you can pass something like this 1-50 and then split on '-' and construct range. Something like this:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--l1', type=str, help="two numbers separated by a hyphen")
parser.add_argument('--l2', type=str)
args = parser.parse_args()
l1_list_range = xrange(*args.l1.split('-')) # xrange(1,50)
for i in l1_list_range:
    print i

Example: python prog.py --l1=1-50

Logic I think you can write yourself. :)

Solution 2

argparse supports nargs parameter, which tells you how many parameters it eats. When nargs="+" it accepts one or more parameters, so you can pass -b 1 2 3 4 and it will be assigned as a list to b argument

# args.py
import argparse

p = argparse.ArgumentParser()

# accept two lists of arguments
# like -a 1 2 3 4 -b 1 2 3
p.add_argument('-a', nargs="+", type=int)
p.add_argument('-b', nargs="+", type=int)
args = p.parse_args()

# check if input is valid
set_a = set(args.a)
set_b = set(args.b)

# check if "a" is in proper range.
if len(set_a - set(range(1, 51))) > 0: # can use also min(a)>=1 and max(a)<=50
    raise Exception("set a not in range [1,50]")

# check if "b" is in "a"
if len(set_b - set_a) > 0:
    raise Exception("set b not entirely in set a")

# you could even skip len(...) and leave just operations on sets
# ...

So you can run:

$ python arg.py  -a 1 2 3 4 -b 2 20
Exception: set b not entirely in set a

$ python arg.py  -a 1 2 3 4 60 -b 2
Exception: set a not in range [1,50]

And this is valid:

$ python arg.py  -a 1 2 3 4 -b 2 3

Solution 3

This worked for me:

parser.add_argument('-i', '--ids', help="A comma separated list IDs", type=lambda x: x.split(','))

EDIT:

I have just realised that this doesn't actually answer the question being asked. Jakub has the correct solution.

Solution 4

The way that optparse and argparse work is they read arguments from the command line, arguments are split by white-space, so if you want to input your list of integers through the command line interfact from optparse or argparse - you can do this by removing the spaces, or by surrounding your argument with ", example:

> my_script.py --a "1 2 3 4 5" --b "1 2"

or:

> my_script.py --a 1,2,3,4,5 --b  1,2

Your script then needs to convert these inputs into an actual list.

Using argparse syntax (very similar for optparse):

# with spaces and "
a_lst = [i for i in args.a.split(' ')] 
b_lst = [i for i in args.b.split(' ')]

# without spaces and ,
a_lst = [i for i in args.a.split(',')] 
b_lst = [i for i in args.b.split(',')]

Another way to do this would be by either importing the module you want to run and passing the list objects to a class that deals with your code, or by using a while loop and raw_input/input to collect the desired list.

Solution 5

If the only arguments are the lists and the separators, you can do it relatively simply:

sa = sys.argv.index('-a')
sb = sys.argv.index('-b')
lista = [int(i) for i in sys.argv[sa+1:sb]]
listb = [int(i) for i in sys.argv[sb+1:]]

Adding validation is easy:

aval = [i for i in lista if i>1 and i<50]
if len(aval) < len(lista):
    print 'The -a list contains invalid numbers.'
bval = [i for i in listb if i>1 and i<50]
if len(bval) < len(listb):
    print 'The -b list contains invalid numbers.'

Producing a help message:

if sys.argv[1] in ['-h', '-H'] or len(sys.argv) == 1:
    print "Usage: <name> -a [list of integers] -b [list of integers]"
Share:
36,041
Swati
Author by

Swati

Updated on July 06, 2020

Comments

  • Swati
    Swati almost 4 years

    I want to pass 2 lists of integers as input to a python program.

    For e.g, (from command line)

    python test.py --a 1 2 3 4 5 -b 1 2  
    

    The integers in this list can range from 1-50, List 2 is subset of List1.
    Any help/suggestions ? Is argparse the right module ? Any concerns in using that ?

    I have tried :

    import argparse
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('--a', help='Enter list 1 ')
        parser.add_argument('--b', help='Enter list 2 ')
        args = parser.parse_args()
        print (args.a)
    
  • Swati
    Swati about 11 years
    Any sample code to do that ? I also want to throw error if any list is empty or contains the number out of range ?
  • Ellochka Cannibal
    Ellochka Cannibal about 11 years
    Please bring a sample list that you want to pass.
  • Burhan Khalid
    Burhan Khalid about 11 years
    @Swati StackOverflow is not a code writing service. Please make an attempt yourself at the problem and then ask for help with your solution.
  • Swati
    Swati about 11 years
    sample list list1 contains number 1-50 and list2 contains subset of number from list1
  • Swati
    Swati about 11 years
    I like your approach, how do I provide help regarding the input parameters and any validation about the range ?
  • Ellochka Cannibal
    Ellochka Cannibal about 11 years
    good decision! true if it is necessary to list the 50 numbers, not 5, it is long))
  • Jakub M.
    Jakub M. about 11 years
    Because what you ask for is set checking. When you check if B is in A, it is set operation - check if set b - set a is empty. For ranges, I could use min(a) >= 1 and max(a) <= 50, although I wanted to be consistent. You asked about "List 2 is subset of List1.", no?
  • Inbar Rose
    Inbar Rose about 11 years
    For validity checking, why not use if all(1 <= a <= 50 for a in set_a) ?
  • Jakub M.
    Jakub M. about 11 years
    @InbarRose: nice one, if I refactored it, I would use it