def map_postcodes_to_constituencies(postcode_file, constituencies, ids):
    with open(postcode_file) as f:
        postcode_constituencies = {}
        unknowns = []
        last_constituencies = [constituencies.keys()[0]]*5
        n = 0

        for postcode,point in postcodes_to_points(f):
            constituency = None
            n += 1
            
            # The postcodes are in alphabetical order - so it's relatively
            # likely that this postcode will be in the same constituency as one
            # of the last five postcodes.  Check those first.

            for guess in reversed(last_constituencies):
                if constituencies[guess].contains(point):
                    last_constituencies.remove(guess)
                    constituency = guess
            
            # If that didn't work, we should loop through every constituency.

            if postcode not in postcode_constituencies:
                for possible_constituency in constituencies.keys():
                    if constituencies[possible_constituency].contains(point):
                        constituency = possible_constituency
                        break

            # Sometimes we don't get a result, usually because of postcodes on
            # Scottish islands which fall outside the constituency boundaries
            # we're using.  Make a best guess.

            if constituency is None:
                constituency = guess_constituency(postcode, point, constituencies)

            if constituency not in ids:
                ids[constituency] = waw_app.models.Constituency.objects.filter(
                    name__exact=constituency)[0]
            
            new_postcode = waw_app.models.Postcode.objects.create(
                postcode=postcode, constituency=ids[constituency])
            new_postcode.save()
            last_constituencies.append(constituency)
def map_postcodes_to_constituencies(postcode_file, constituencies, verbose=False):
    with open(postcode_file) as f:
        postcode_constituencies = {}
        unknowns = []
        last_constituencies = [constituencies.keys()[0]] * 5
        n = 0

        for postcode, point in postcodes_to_points(f):
            n += 1

            # The postcodes are in alphabetical order - so it's relatively
            # likely that this postcode will be in the same constituency as one
            # of the last five postcodes.  Check those first.

            for guess in last_constituencies:
                if constituencies[guess].contains(point):
                    last_constituencies.remove(guess)
                    postcode_constituencies[postcode] = guess
                    last_constituencies.append(guess)

            # If that didn't work, we should loop through every constituency.

            if postcode not in postcode_constituencies:
                for constituency in constituencies.keys():
                    if constituencies[constituency].contains(point):
                        postcode_constituencies[postcode] = constituency
                        last_constituencies.append(constituency)
                        break

            # Sometimes we don't get a result, usually because of postcodes on
            # Scottish islands which fall outside the constituency boundaries
            # we're using.  Collect those postcodes into a list of unknowns,
            # for further processing (eg. a lookup on http://parliament.uk or a
            # best guess by distance).

            if postcode not in postcode_constituencies:
                unknowns.append((postcode, point))

            if verbose and 0 == (n % 1000):
                print("%d postcodes processed" % n)

    return (postcode_constituencies, unknowns)