use a regex or not?

Kent Johnson kent37 at tds.net
Tue Jun 21 11:15:51 EDT 2005


Joost Jacob wrote:
> I am looking for a function that takes an input string
> and a pattern, and outputs a dictionary.

Here is one way. I won't say it's pretty but it is fairly straightforward and it passes all your tests.

Kent

def fill(s, p):
    """
    >>> fill('ab', p='aA')
    {'A': 'b'}

    >>> fill('ab', p='Ab')
    {'A': 'a'}

    >>> fill('bb', p='Aa')      # no match
    {}

    >>> fill('aa', p='Aa')
    {'A': 'a'}

    >>> fill('aa', p='Ab')      # no match
    {}

    >>> fill('abb', p='aA')
    {'A': 'bb'}

    >>> fill('aba', p='aAa')
    {'A': 'b'}

    >>> fill('abb', p='aAa')    # no match
    {}

    >>> fill('abab', p='aAaA')  # A-matches must be equal
    {'A': 'b'}

    >>> fill('abac', p='aAaA')  # no match
    {}

    >>> fill('abac', p='aAaB')
    {'A': 'b', 'B': 'c'}
    """
    
    # If s is longer than p the extra chars of s become part of the
    # last item of s
    if len(s) > len(p):
        ss = list(s[:len(p)])
        ss[-1] = ss[-1] + s[len(p):]
        s = ss
        
    d = {}
    seen = {}
    
    for s1, p1 in zip(s, p):
        # Lower case have to map to themselves
        if p1.islower() and s1 != p1:
#            print 'Non-identity map for %s: %s' % (p1, s1)
            return {}
            
        try:
            # Check for multiple mappings from p1
            old_s = d[p1]
            
            if old_s != s1:
                # We saw this s before but the mapping is different
                return {}
            
            # We saw this s1, p1 before with the same mapping
            continue
            
        except KeyError:
            # Check for multiple mappings to p1
            if seen.get(s1, p1.lower()) != p1.lower():
                return {}
        
        # This is a new mapping
        d[p1] = s1
        seen[s1] = p1.lower()
    
    
    # Strip out the lower case mappings
    return dict((k, v) for k, v in d.iteritems() if k.isupper())

def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()



More information about the Python-list mailing list