Path: csiph.com!optima2.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!1.eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed8.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; '16,': 0.03; 'anyway.': 0.04; 'linear': 0.07; 'though:': 0.07; 'type,': 0.07; 'val': 0.07; 'cc:addr:python-list': 0.09; 'check.': 0.09; 'craft': 0.09; 'dict': 0.09; 'targets': 0.09; 'tuple': 0.09; 'def': 0.13; 'properly': 0.15; 'thu,': 0.15; 'first)': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'item):': 0.16; 'lookups': 0.16; 'mismatch': 0.16; 'search:': 0.16; 'sequential': 0.16; 'subject:Mapping': 0.16; 'subject:key': 0.16; 'wrote:': 0.16; 'try:': 0.18; 'thanks.': 0.18; '2015': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'do.': 0.22; 'keys': 0.22; 'code,': 0.23; 'matching': 0.23; "python's": 0.23; 'header :In-Reply-To:1': 0.24; "doesn't": 0.26; 'message- id:@mail.gmail.com': 0.27; 'about.': 0.29; 'hash': 0.29; 'short,': 0.29; 'talked': 0.29; 'raise': 0.29; "i'm": 0.30; "i'd": 0.31; 'probably': 0.31; "can't": 0.32; 'skip:_ 10': 0.32; 'help,': 0.32; 'class': 0.33; 'steven': 0.33; 'case,': 0.34; 'except': 0.34; 'gives': 0.35; 'received:google.com': 0.35; 'could': 0.35; 'mapping': 0.35; 'something': 0.35; 'but': 0.36; 'too': 0.36; 'pm,': 0.36; 'subject:: ': 0.37; 'really': 0.37; 'turn': 0.37; 'suggestion': 0.37; 'skip:z 10': 0.38; 'means': 0.39; 'sure': 0.39; 'subject:with': 0.40; 'still': 0.40; 'your': 0.60; 'per': 0.62; 'benefit': 0.66; 'virtually': 0.66; 'teach': 0.70; 'jul': 0.72; 'honest': 0.76; 'chrisa': 0.84; 'concept,': 0.84; "it'd": 0.84; 'subscripts': 0.84; 'ultimately,': 0.84; 'to:none': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=R/+qxh1Pek6GkL+DG2pnM+KbrM+d9/M9eue2UimPLlc=; b=0B28jugJ8M2O6EN6xhJSK+UtCNKTQaewY0TlDzDDKD07UGvSxr6CgJcjGCubEIENjG NNKrW4dHD4cyQC9vEOMWcH5zbhNphLyUl+tWxygNdf4/YrOVjrs0Xpm8s19eztnwB1Tj ov+9aj392tk26dBKLg++VPnUqPrxB/NG5oe/Hg935LPUOSZJILneBFECaid7lMglOAwZ EE+8u+Fh9J+HaIYELuVQiG3GZJKR6W/OT39qFvHm/LDs2EZGEjDHyPx3FeVF3n86IGX6 F4LZAKHvggCO8oqBZegZLwtv2k2T6FTDBUyBs0OgQAT7IK/RQ84TEsmpra9txlxl3QT4 QsJA== MIME-Version: 1.0 X-Received: by 10.107.165.142 with SMTP id o136mr10412044ioe.120.1437027682095; Wed, 15 Jul 2015 23:21:22 -0700 (PDT) In-Reply-To: <85bnfcve7w.fsf@benfinney.id.au> References: <85k2u0vpis.fsf@benfinney.id.au> <85bnfcve7w.fsf@benfinney.id.au> Date: Thu, 16 Jul 2015 16:21:22 +1000 Subject: Re: Mapping, with sequence as key, wildcard and subsequence matching From: Chris Angelico Cc: "python-list@python.org" Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 35 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1437027691 news.xs4all.nl 2837 [2001:888:2000:d::a6]:47542 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:93900 On Thu, Jul 16, 2015 at 3:55 PM, Ben Finney wrote: > Thanks. The part which puzzle me though: How do we teach the mapping > type about that matching behaviour? I'm not sure you really need a mapping type per se. The benefit of something like Python's dict is that it gives really fast lookups via the hash table... but with the "match any" concept, there's actually a potential for ambiguities, which means you need a sequential (strictest first) check. In any case, it's virtually impossible to hash a tuple of strings such that it can match multiple targets, based only on what the targets do. Steven's suggestion to turn this into an honest linear search is probably what I'd do; ultimately, a dict that can't hash its keys properly is going to devolve to that anyway. You could craft a mapping-like type that uses subscripts in this way. I'm not sure whether it'd help, but there's no particular reason for __getitem__ to not do a full linear search: class Lookup: def __getitem__(self, item): for matcher, value in self.stuff: keys = iter(item) for key in matcher: if key is ZERO_OR_MORE: return value # Matched! try: val = next(keys) except StopIteration: break # Too short, doesn't match if key != val and key is not ANY_ONE: break # Mismatch else: return value # Matched! raise KeyError(item) Then in your code, it would look like any other mapping type, but it'd still be the exact same linear search that Steven talked about. ChrisA