// // NameParser.m // Port of Greg Miernicki's PHP NameParser // // Created by Mark Pemburn on 2/7/13. // Copyright (c) 2013 Pemburnia LLC. All rights reserved. // #import "NameParser.h" @implementation NameParser { NSArray *prefixes; NSArray *surnamePrefixes; NSArray *suffixes; } @synthesize prefix, firstName, middleName, lastName, suffix; - (id) initWithFullName: (NSString *) fullName { self = [super init]; if (self) { prefixes = [[NSArray alloc] initWithObjects: @"sr", @"dr", @"doctor", @"miss", @"misses", @"mr", @"mister", @"mrs", @"ms", @"judge", @"sir", @"madam", @"madame", @"AB", @"2ndLt", @"Amn", @"1stLt", @"A1C", @"Capt", @"SrA", @"Maj", @"SSgt", @"LtCol", @"TSgt", @"Col", @"BrigGen", @"1stSgt", @"MajGen", @"SMSgt", @"LtGen", @"1stSgt", @"Gen", @"CMSgt", @"1stSgt", @"CCMSgt", @"CMSAF", @"PVT", @"2LT", @"PV2", @"1LT", @"PFC", @"CPT", @"SPC", @"MAJ", @"CPL", @"LTC", @"SGT", @"COL", @"SSG", @"BG", @"SFC", @"MG", @"MSG", @"LTG", @"1SGT", @"GEN", @"SGM", @"CSM", @"SMA", @"WO1", @"WO2", @"WO3", @"WO4", @"WO5", @"ENS", @"SA", @"LTJG", @"SN", @"LT", @"PO3", @"LCDR", @"PO2", @"CDR", @"PO1", @"CAPT", @"CPO", @"RADM(LH]", @"SCPO", @"RADM(UH]", @"MCPO", @"VADM", @"MCPOC", @"ADM", @"MPCO-CG", @"CWO-2", @"CWO-3", @"CWO-4", @"Pvt", @"2ndLt", @"PFC", @"1stLt", @"LCpl", @"Capt", @"Cpl", @"Maj", @"Sgt", @"LtCol", @"SSgt", @"Col", @"GySgt", @"BGen", @"MSgt", @"MajGen", @"1stSgt", @"LtGen", @"MGySgt", @"Gen", @"SgtMaj", @"SgtMajMC", @"WO-1", @"CWO-2", @"CWO-3", @"CWO-4", @"CWO-5", @"ENS", @"SA", @"LTJG", @"SN", @"LT", @"PO3", @"LCDR", @"PO2", @"CDR", @"PO1", @"CAPT", @"CPO", @"RDML", @"SCPO", @"RADM", @"MCPO", @"VADM", @"MCPON", @"ADM", @"FADM", @"WO1", @"CWO2", @"CWO3", @"CWO4", @"CWO5", nil]; surnamePrefixes = [[NSArray alloc] initWithObjects: @"bon", @"ben", @"bin", @"da", @"dal", @"de", @"del", @"der", @"de", @"e", @"la", @"le", @"lo", @"los", @"san", @"st", @"ste", @"van", @"vel", @"von", nil]; suffixes = [[NSArray alloc] initWithObjects: @"dds", @"esq", @"esquire", @"jr", @"sr", @"2", @"i", @"ii", @"iii", @"iv", @"v", @"clu", @"chfc", @"cfp", @"md", @"phd", nil]; [self parse: fullName]; } return self; } - (void) parse: (NSString *) fullName { prefix = @""; firstName = @""; middleName = @""; lastName = @""; suffix = @""; NSArray *nameParts = [[self pregReplace: fullName withString: @" " usingPattern: @"[ \t\n]+"] componentsSeparatedByString: @","]; int numPieces = [nameParts count]; switch (numPieces) { case 1: [self withoutComma: nameParts]; break; default: [self withComma: nameParts]; break; } } - (void) withComma: (NSArray *)nameParts { int i, s; NSString *current; NSString *next; int numPieces = [nameParts count]; if ([self inArray: suffixes find: [nameParts objectAtIndex: 1]]) { NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 0]] componentsSeparatedByString: @" "]; int numSubPieces = [subPieces count]; for (i = 0; i < numSubPieces; i++) { current = [self trim: [subPieces objectAtIndex: i]]; if (i < (numSubPieces - 1)) { next = [self trim: [subPieces objectAtIndex: i + 1]];; } else { next = @""; } if (i == 0 && [self inArray: prefixes find: current]) { [self setPrefix: current]; continue; } if ([firstName isEqualToString: @""]) { [self setFirstName: current]; continue; } if (i == numSubPieces - 1) { [self setLastNameToCurrent: current]; continue; } if ([self inArray: surnamePrefixes find: current]) { [self setLastNameToCurrent: current]; continue; } if ([next isEqualToString: @"y"] || [next isEqualToString: @"Y"]) { [self setLastNameToCurrent: current]; continue; } if (![lastName isEqualToString: @""]) { lastName = [NSString stringWithFormat: @"%@ %@", lastName, current]; continue; } [self setMiddleNameToCurrent: current]; } suffix = [self trim: [nameParts objectAtIndex: 1]]; for (i = 2; i < numPieces; i++) { suffix = [NSString stringWithFormat: @"%@, %@", suffix, [self trim: [nameParts objectAtIndex: 1]]]; } } else { NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 1]] componentsSeparatedByString: @" "]; int numSubPieces = [subPieces count]; for (i = 0; i < numSubPieces; i++) { current = [self trim: [subPieces objectAtIndex: i]]; if (i < (numSubPieces - 1)) { next = [self trim: [subPieces objectAtIndex: i + 1]];; } else { next = @""; } if (i == 0 && [self inArray: prefixes find: current]) { [self setPrefix: current]; continue; } if ([firstName isEqualToString: @""]) { [self setFirstName: current]; continue; } if (i == numSubPieces - 2 && ![next isEqualToString: @""] && [self inArray: suffixes find: next]) { [self setMiddleNameToCurrent: current]; suffix = [NSString stringWithFormat: @"%@", next]; break; } if (i == numSubPieces - 1 && [self inArray: suffixes find: current]) { suffix = [NSString stringWithFormat: @"%@", current]; continue; } [self setMiddleNameToCurrent: current]; } NSString *lastPart = [nameParts lastObject]; if (lastPart != nil && ![lastPart isEqualToString: @""]) { if ([lastName isEqualToString: @""]) { suffix = [NSString stringWithFormat: @"%@", lastPart]; for (s = 3; s < numPieces; s++) { suffix = [NSString stringWithFormat: @", %@", [self trim: [nameParts objectAtIndex: s]]]; } } else { for (s = 2; s < numPieces; s++) { suffix = [NSString stringWithFormat: @", %@", [self trim: [nameParts objectAtIndex: s]]]; } } } lastName = [NSString stringWithFormat: @"%@", [nameParts objectAtIndex: 0]]; } } - (void) withoutComma: (NSArray *)nameParts { NSArray *subPieces = [[self trim: [nameParts objectAtIndex: 0]] componentsSeparatedByString: @" "]; int numSubPieces = [subPieces count]; int i; NSString *current; NSString *next; for (i = 0; i < numSubPieces; i++) { current = [self trim: [subPieces objectAtIndex: i]]; if (i < (numSubPieces - 1)) { next = [self trim: [subPieces objectAtIndex: i + 1]];; } else { next = @""; } if (i == 0 && [self inArray: prefixes find: current]) { [self setPrefix: current]; continue; } if ([firstName isEqualToString: @""]) { [self setFirstName: current]; continue; } if (i == numSubPieces - 2 && ![next isEqualToString: @""] && [self inArray: suffixes find: next]) { [self setLastNameToCurrent: current]; suffix = [NSString stringWithFormat: @"%@", next]; break; } if (i == numSubPieces - 1) { [self setLastNameToCurrent: current]; continue; } if ([self inArray: surnamePrefixes find: current]) { [self setLastNameToCurrent: current]; continue; } if ([next isEqualToString: @"y"] || [next isEqualToString: @"Y"]) { [self setLastNameToCurrent: current]; continue; } if (![lastName isEqualToString: @""]) { lastName = [NSString stringWithFormat: @"%@ %@", lastName, current]; continue; } [self setMiddleNameToCurrent: current]; } } - (void) setLastNameToCurrent: (NSString *)current { if (![lastName isEqualToString: @""]) { lastName = [NSString stringWithFormat: @"%@ %@", lastName, current]; } else { lastName = [NSString stringWithFormat: @"%@", current]; } } - (void) setMiddleNameToCurrent: (NSString *)current { if (![middleName isEqualToString: @""]) { middleName = [NSString stringWithFormat: @"%@ %@", middleName, current]; } else { middleName = [NSString stringWithFormat: @"%@", current]; } } - (BOOL) inArray: (NSArray *)haystack find: (NSString *)needle { needle = [[needle lowercaseString] stringByReplacingOccurrencesOfString: @"." withString: @""]; needle = [self trim: needle]; return [haystack containsObject: needle]; } - (NSString *) pregReplace: (NSString *)string withString: (NSString *)replace usingPattern: (NSString *)pattern { NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: pattern options: NSRegularExpressionCaseInsensitive error: &error]; NSString *modifiedString = [regex stringByReplacingMatchesInString: string options: 0 range: NSMakeRange(0, [string length]) withTemplate: replace]; return modifiedString; } - (NSString *)trim: (NSString *)string { return [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; } @end