Python argparse: Force a list item to be unique

后端 未结 4 1704
广开言路
广开言路 2021-01-19 16:17

Being able to validate the list items using choices=servers below is nice.

servers = [ \"ApaServer\", \"BananServer\", \"GulServer\", \"SolServ         


        
相关标签:
4条回答
  • 2021-01-19 16:46

    Modifying Michel's answer:

    In [1]: x = [5,6,5]
    
    In [2]: x_nodups = list(set(x))
    
    In [3]: x_nodups
    Out[3]: [5, 6]
    
    In [4]: x_nodups_michel = dict(map(lambda i: (i,1),x)).keys()
    
    In [5]: x_nodups_michel
    Out[5]: [5, 6]
    

    Much shorter.

    0 讨论(0)
  • 2021-01-19 16:51

    Here's an excerpt from some code that I use for a similar purpose:

    def parse_args(argv):
        class SetAction(argparse.Action):
            """argparse.Action subclass to store distinct values"""
            def __call__(self, parser, namespace, values, option_string=None):
                try:
                    getattr(namespace,self.dest).update( values )
                except AttributeError:
                    setattr(namespace,self.dest,set(values))
        ap = argparse.ArgumentParser(
            description = __doc__,
            formatter_class = argparse.ArgumentDefaultsHelpFormatter,
            )
        ap.add_argument('--genes', '-g',
                        type = lambda v: v.split(','),
                        action = SetAction,
                        help = 'select by specified gene')
    

    This is similar in spirit to jcollado's reply, with a modest improvement: multiple options can be specified, with comma separated values, and they are deduped (via set) across all options.

    For example:

    snafu$ ./bin/ucsc-bed -g BRCA1,BRCA2,DMD,TNFA,BRCA2 -g BRCA1
    Namespace(genes=set([u'BRCA1', u'BRCA2', u'DMD', u'TNFA']))
    

    Note that there are two -g args. BRCA2 is specified twice in the first, but appears only once. BRCA1 is specified in the first and second -g opts, but also appears only once.

    0 讨论(0)
  • 2021-01-19 16:55

    I don't think, that you can enforce this with argparse, but I also don't see any reason to do so. Just document in help that duplicates are ignored. If the user passes duplicate arguments to --only, just let her do so, and ignore the duplicate argument when processing the option arguments (e.g. by turing the list into a set() before processing).

    0 讨论(0)
  • 2021-01-19 17:04

    The way to properly discard duplicates using argparse would be to create your own argparse.Action class that takes care of using set as suggestted by other answers:

    import argparse
    
    class UniqueAppendAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            unique_values = set(values)
            setattr(namespace, self.dest, unique_values)
    
    servers = ["ApaServer", "BananServer", "GulServer", "SolServer",
               "RymdServer", "SkeppServer", "HavsServer", "SovServer" ]
    parser = argparse.ArgumentParser()
    parser.add_argument('-o', '--only', nargs='*', choices=servers, action=UniqueAppendAction,
                        help='Space separated list of case sensitive server names to process')
    print parser.parse_args()
    

    Example output:

    $ python test.py -o ApaServer ApaServer
    Namespace(only=set(['ApaServer']))
    
    0 讨论(0)
提交回复
热议问题