1

I have found a few posts on here with similar questions but not entirely the same as what I am trying. I am currently using a simple if statement that checks the data the user enters then checks to see if it starts with a number of different values. I am doing this with the following:

var value = string;
var value = value.toLowerCase();
country = "NONE";
county = "NONE";

if (value.indexOf('ba1 ') == 0 || value.indexOf('ba2 ') == 0 || value.indexOf('ba3 ') == 0) { //CHECK AVON (MAINLAND UK) UK.AVON
    country = "UK";
    county = "UK.AVON";
} else if(value.indexOf('lu') == 0){//CHECK BEDFORDSHIRE (MAINLAND UK) UK.BEDS
    country = "UK";
    county = "UK.BEDS";
}

I have about 20-30 different if, else statements that are basically checking the post code entered and finding the county associated. However some of these if statements are incredibly long so I would like to store the values inside an array and then in the if statement simply check value.indexOf() for each of the array values.

So in the above example I would have an array as follows for the statement:

var avon = new Array('ba1 ','ba 2','ba3 ');

then inside the indexOf() use each value

Would this be possible with minimal script or am I going to need to make a function for this to work? I am ideally wanting to keep the array inside the if statement instead of querying for each array value.

Simon Staton
  • 4,345
  • 4
  • 27
  • 49
  • 1
    Just FYI: `indexOf` and `$.inArray` does the same thing. – Johan Sep 18 '13 at 14:28
  • Be careful - postcode area boundaries do not necessarily align with county boundaries, see e.g. SN6 which covers bits of Oxfordshire _and_ Wiltshire. – Alnitak Sep 18 '13 at 14:31
  • I actually live in "sn7" which is oxfordshire but shows as swindon, have taken this into account already which is why my arrays are so damn long! It's a small world if you are an sn6 ;) – Simon Staton Sep 18 '13 at 14:32
  • hehe, just down the road from me, then (OX13). My point though is that SN6 _by itself_ doesn't identify the county. – Alnitak Sep 18 '13 at 14:32
  • Very small world! And yes very true – Simon Staton Sep 18 '13 at 14:33
  • Also, FWIW, the Royal Mail doesn't care about counties in addresses any more. The largest "geographical" unit they care about for disambiguation purposes is the "postal town". – Alnitak Sep 18 '13 at 14:37
  • Well the county field isn't even imported into our courier software. It's just so when the user is checking out they are comfortable with the process. It's also a required field in the CMS we use sadly. – Simon Staton Sep 18 '13 at 14:38
  • Personally, I think you need to get a better postcode parser first, that splits the two halves of the postcode better. Some end users will inevitably omit the space, and you then have to figure whether `OX18` is the start of `OX1 8xx` or `OX18 nxx`. Once you've done that, personally I'd just create a direct static object of inbound prefix -> county values. – Alnitak Sep 18 '13 at 14:43
  • I agree, the space was a huge issue when I made this. In the end I made it check all double digit starting postcodes `OX12 XXX` then if it hasnt found that check the single digits `OX1 ` but again these needs them to use a space, I can maybe make it force the space in the input box. – Simon Staton Sep 18 '13 at 14:58

4 Answers4

2

You can use the some Array method (though you might need to shim it for legacy environments):

var value = string.toLowerCase(),
    country = "NONE",
    county = "NONE";

if (['ba1 ','ba 2','ba3 '].some(function(str) {
    return value.slice(0, str.length) === str;
})) {
    country = "UK";
    county = "UK.AVON";
}

(using a more performant How to check if a string "StartsWith" another string? implementation also)

For an even shorter condition, you might also resort to regex (anchor and alternation):

if (/^ba(1 | 2|3 )/i.test(string)) { … }
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

No, it doesn’t exist, but you can make a function to do just that:

function containsAny(string, substrings) {
    for(var i = 0; i < substrings.length; i++) {
        if(string.indexOf(substrings[i]) !== -1) {
            return true;
        }
    }

    return false;
}

Alternatively, there’s a regular expression:

/ba[123] /.test(value)
Ry-
  • 218,210
  • 55
  • 464
  • 476
0

My recomendation is to rethink your approach and use regular expressions instead of indexOf.

But if you really need it, you can use the following method:

function checkStart(value, acceptableStarts){
  for (var i=0; i<acceptableStarts.length; i++) {
    if (value.indexOf(acceptableStarts[i]) == 0) {
      return true;
    } 
  }
  return false;
}

Your previous usage turns into:

if (checkStart(value, ['ba1', ba2 ', 'ba3'])) {
  country = 'UK';
}

Even better you can generalize stuff, like this:

var countryPrefixes = {
  'UK' : ['ba1','ba2 ', 'ba3'],
  'FR' : ['fa2','fa2']
}


for (var key in countryPrefixes) {
  if (checkStart(value, countryPrefixes[key]) {
     country = key;
  }
}
Tibos
  • 27,507
  • 4
  • 50
  • 64
0

I'd forget using hard-coded logic for this, and just use data:

var countyMapping = {
    'BA1': 'UK.AVON',
    'BA2': 'UK.AVON',
    'BA3': 'UK.AVON',
    'LU': 'UK.BEDS',
    ...
};

Take successive characters off the right hand side of the postcode and do a trivial lookup in the table until you get a match. Four or so lines of code ought to do it:

function getCounty(str) {
    while (str.length) {
        var res = countyMapping[str];
        if (res !== undefined) return res;
        str = str.slice(0, -1);
    }
}

I'd suggest normalising your strings first to ensure that the space between the two halves of the postcode is present and in the right place.

For extra bonus points, get the table out of a database so you don't have to modify your code when Scotland gets thrown out of leaves the UK ;-)

Alnitak
  • 334,560
  • 70
  • 407
  • 495