├── .gitattributes ├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── .vs ├── VSWorkspaceState.json └── slnx.sqlite ├── BinaryFog.NameParser.Tests ├── AfricanNamesTests.cs ├── BinaryFog.NameParser.Tests.csproj ├── CanadianMPsTests.cs ├── DataFiles.cs ├── DataFiles │ ├── AfricanNames.xml │ ├── CanadianMPs.xml │ ├── USRepresentatives.json │ └── USSenators.json ├── ExtraCasesTests.cs ├── FullNameParserTest.cs ├── InitialAsMiddleNameTests.cs ├── MGuinessParserTests.cs ├── MattGilletesParserTests.cs ├── PFornessParserTests.cs ├── Properties │ └── launchSettings.json ├── RandomNamesTests.cs ├── TestFullNamePattern.cs ├── ThirdPartyIntegrationTests.cs ├── USRepresentativesTests.cs └── USSenatorsTests.cs ├── BinaryFog.NameParser.sln ├── BinaryFog.NameParser.sln.DotSettings ├── BinaryFog.NameParser.sln.GhostDoc.xml ├── BinaryFog.NameParser ├── BinaryFog.NameParser.csproj ├── ExcludeFromCodeCoverageAttribute.cs ├── FullNameParser.cs ├── Helpers.cs ├── IFullNamePattern.cs ├── NameComponentSets.cs ├── ParsedFullName.cs ├── Patterns │ ├── AfricanFirstLastPattern.cs │ ├── CompanyPattern.cs │ ├── FirstHyphenatedLastNickPattern.cs │ ├── FirstHyphenatedLastPattern.cs │ ├── FirstInitialHyphenatedLastPattern.cs │ ├── FirstInitialHyphenatedLastSuffixPattern.cs │ ├── FirstInitialLastCommaSuffixPattern.cs │ ├── FirstInitialLastPattern.cs │ ├── FirstInitialLastSuffixPattern.cs │ ├── FirstInitialPrefixedLastPattern.cs │ ├── FirstInitialPrefixedLastSuffixPattern.cs │ ├── FirstIrishLastPattern.cs │ ├── FirstLastNickPattern.cs │ ├── FirstLastPattern.cs │ ├── FirstLastSuffixPattern.cs │ ├── FirstLastSuffixSuffixPattern.cs │ ├── FirstMiddleHyphenatedLastPattern.cs │ ├── FirstMiddleHyphenatedLastSuffixPattern.cs │ ├── FirstMiddleLastPattern.cs │ ├── FirstMiddleLastSuffixPattern.cs │ ├── FirstMiddlePrefixedLastPattern.cs │ ├── FirstMiddlePrefixedLastSuffixPattern.cs │ ├── FirstMiddleTwoLastPattern.cs │ ├── FirstNameJobTitlePattern.cs │ ├── FirstNickHyphenatedLastPattern.cs │ ├── FirstNickInitialLastPattern.cs │ ├── FirstNickLastPattern.cs │ ├── FirstNickMiddleHyphenatedLastPattern.cs │ ├── FirstNickMiddleLastPattern.cs │ ├── FirstPrefixedLastPattern.cs │ ├── FirstPrefixedLastSuffixPattern.cs │ ├── FirstTwoHyphenatedMiddleLastPattern.cs │ ├── FirstTwoLastPattern.cs │ ├── FirstTwoMiddleHyphenatedLastPattern.cs │ ├── FirstTwoMiddleLastPattern.cs │ ├── HyphenatedFirstLastPattern.cs │ ├── LastNameCommaFirstNameInitialPattern.cs │ ├── LastNameCommaFirstNameMiddleNameSuffixPattern.cs │ ├── LastNameCommaFirstNameNickNameInitialPattern.cs │ ├── LastNameCommaFirstNamePattern.cs │ ├── SingleHyphenatedLastNameCommaFirstNameMiddleName.cs │ ├── SingleHyphenatedLastNameCommaFirstNameMiddleNameSuffixPattern.cs │ ├── SingleHyphenatedNameOnlyPattern.cs │ ├── SingleNameOnlyPattern.cs │ ├── TitleFirstHyphenatedLastPattern.cs │ ├── TitleFirstInitialLastPattern.cs │ ├── TitleFirstInitialLastSuffixPattern.cs │ ├── TitleFirstInitialPrefixedLastSuffixPattern.cs │ ├── TitleFirstIrishLastPattern.cs │ ├── TitleFirstLastPattern.cs │ ├── TitleFirstLastSuffixPattern.cs │ ├── TitleFirstMiddlePrefixedLastSuffixPattern.cs │ ├── TitleFirstNameJobTitlePattern.cs │ ├── TitleFirstNickLastPattern.cs │ ├── TitleFirstNickLastSuffixPattern.cs │ ├── TitleFirstPrefixedLastPattern.cs │ ├── TitleFirstTwoLastPattern.cs │ ├── TitleFirstTwoMiddlePrefixedLastSuffixPattern.cs │ ├── TitleHyphenatedFirstLastPattern.cs │ ├── TwoInitialsFirstLastPattern.cs │ ├── TwoInitialsFirstLastSuffixPattern.cs │ ├── TwoInitialsFirstOptionalDotFirstLastPattern.cs │ └── TwoInitialsSecondOptionalDotFirstLastPattern.cs ├── Properties │ └── AssemblyInfo.cs ├── RegexNameComponents.cs ├── Resources.cs └── Resources │ ├── 999230.jpg │ ├── CompanySuffixes.txt │ ├── FemaleFirstNames.txt │ ├── JobTitles.txt │ ├── LastNamePrefixes.txt │ ├── LastNames.txt │ ├── MaleFirstNames.txt │ ├── PostNominals.txt │ ├── Suffixes.txt │ └── Titles.txt ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: .NET 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Setup .NET 17 | uses: actions/setup-dotnet@v1 18 | with: 19 | dotnet-version: 3.1.x 20 | - name: Restore dependencies 21 | run: dotnet restore 22 | - name: Build 23 | run: dotnet build --no-restore 24 | - name: Test 25 | run: dotnet test --no-build --verbosity normal 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | ## TODO: Comment the next line if you want to checkin your 127 | ## web deploy settings but do note that will include unencrypted 128 | ## passwords 129 | #*.pubxml 130 | 131 | # NuGet Packages Directory 132 | packages/* 133 | ## TODO: If the tool you use requires repositories.config 134 | ## uncomment the next line 135 | #!packages/repositories.config 136 | 137 | # Enable "build/" folder in the NuGet Packages folder since 138 | # NuGet packages use it for MSBuild targets. 139 | # This line needs to be after the ignore of the build folder 140 | # (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # LightSwitch generated files 187 | GeneratedArtifacts/ 188 | _Pvt_Extensions/ 189 | ModelManifest.xml 190 | /.vs 191 | -------------------------------------------------------------------------------- /.vs/VSWorkspaceState.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExpandedNodes": [ 3 | "" 4 | ], 5 | "PreviewInSolutionExplorer": false 6 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfog/NameParser/86d86190fb19b19cc96e046342bb31cac0f7d665/.vs/slnx.sqlite -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/AfricanNamesTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using Xunit; 5 | 6 | 7 | namespace BinaryFog.NameParser.Tests { 8 | public class AfricanNamesTests { 9 | public static IEnumerable GetAfricanNames() 10 | => DataFiles.GetXDocument("AfricanNames.xml")? 11 | .Root?.Elements("Person") 12 | .Select(xe => new object[] { 13 | xe.Element("FirstName")?.Value, 14 | xe.Element("LastName")?.Value, 15 | xe.Element("Name")?.Value, 16 | }); 17 | 18 | [Theory] 19 | [MemberData(nameof(GetAfricanNames), DisableDiscoveryEnumeration = true)] 20 | public void AfricanNames_Test(string firstName, string lastName, string expectedDisplayName) { 21 | // ARRANGE 22 | string fullName = $"{firstName} {lastName}"; 23 | //Console.WriteLine(fullName); 24 | 25 | // ACT 26 | var target = new FullNameParser(fullName); 27 | target.Parse(); 28 | 29 | // ASSERT 30 | Assert.Equal(firstName, target.FirstName); 31 | Assert.Equal(lastName, target.LastName); 32 | Assert.Equal(expectedDisplayName, target.DisplayName); 33 | } 34 | 35 | [Fact] 36 | public void Parse_SenQUOTEDerrickMarks() 37 | { 38 | var fullName = "Sen'Derrick Marks"; 39 | var target = new FullNameParser(fullName); 40 | target.Parse(); 41 | 42 | Assert.Equal("Sen'Derrick", target.FirstName); 43 | Assert.Equal("Marks", target.LastName); 44 | Assert.Equal("Sen'Derrick Marks", target.DisplayName); 45 | Assert.Null(target.Title); 46 | } 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/BinaryFog.NameParser.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | 6 | 7 | 8 | netcoreapp3.1 9 | 10 | library 11 | 12 | 2.0.0 13 | 14 | 15 | 16 | TRACE 17 | 18 | 19 | 20 | 21 | All 22 | 23 | 24 | 25 | All 26 | 27 | 28 | All 29 | 30 | 31 | All 32 | 33 | 34 | All 35 | 36 | 37 | All 38 | 39 | 40 | All 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | PreserveNewest 58 | 59 | 60 | PreserveNewest 61 | 62 | 63 | PreserveNewest 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/CanadianMPsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using Xunit; 6 | 7 | 8 | namespace BinaryFog.NameParser.Tests 9 | { 10 | public class CanadianMPsTests 11 | { 12 | 13 | public static IEnumerable GetCanadianMPs() 14 | => DataFiles.GetXDocument("CanadianMPs.xml")? 15 | .Root?.Elements("MemberOfParliament") 16 | .Select(xe => new object[] { 17 | xe.Element("PersonShortHonorific")?.Value, 18 | xe.Element("PersonOfficialFirstName")?.Value, 19 | xe.Element("PersonOfficialLastName")?.Value, 20 | }); 21 | 22 | 23 | [Theory] 24 | [MemberData(nameof(GetCanadianMPs),DisableDiscoveryEnumeration = true)] 25 | public void CanadianMPs_Test(string title, string firstName, string lastName) 26 | { 27 | //ARRANGE 28 | var firstNames = firstName.Split(new[] {' '}, 2); 29 | var firstFirstName = firstNames[0]; 30 | var secondFirstName = firstNames.Length == 2 ? firstNames[1] : null; 31 | var expectedDisplayName = $"{firstName} {lastName}"; 32 | var fullName = !String.IsNullOrEmpty(title) 33 | ? $"{title} {expectedDisplayName}" 34 | : $"{expectedDisplayName}"; 35 | //Console.WriteLine(fullName); 36 | 37 | //ACT 38 | var target = new FullNameParser(fullName); 39 | target.Parse(); 40 | 41 | //ASSERT 42 | if (!String.IsNullOrEmpty(title)) 43 | Assert.Equal(title, target.Title); 44 | else 45 | Assert.Null(target.Title); 46 | 47 | // Ruth Ellen Brasseau is more likely to be first "Ruth" middle "Ellen" last "Brasseau" 48 | // or first "Ruth" last "Ellen Brasseau" than first "Ruth Ellen" last "Brasseau". 49 | // It would likely be hyphenated ("Ruth-Elen") or joined ("RuthEllen") in general usage. 50 | if (firstName != target.FirstName) { 51 | Assert.Equal(firstFirstName, target.FirstName); 52 | Assert.Equal(secondFirstName, target.MiddleName); 53 | //Assert.Contains(firstName, target.Results.Select(r => r.FirstName)); 54 | } 55 | //Assert.Equal( firstName, target.FirstName); 56 | Assert.Equal( lastName, target.LastName); 57 | 58 | Assert.Equal(expectedDisplayName, target.DisplayName); 59 | } 60 | 61 | 62 | [Fact] 63 | public void Parse_KevinLamoureux() 64 | { 65 | var fullName = "Kevin Lamoureux"; 66 | var target = new FullNameParser(fullName); 67 | target.Parse(); 68 | 69 | Assert.Equal("Kevin", target.FirstName); 70 | Assert.Equal("Lamoureux", target.LastName); 71 | Assert.Equal("Kevin Lamoureux", target.DisplayName); 72 | Assert.Null(target.Title); 73 | } 74 | 75 | [Fact] 76 | public void Parse_JenniferOConnell() 77 | { 78 | var fullName = "Jennifer O'Connell"; 79 | var target = new FullNameParser(fullName); 80 | target.Parse(); 81 | 82 | Assert.Equal("Jennifer", target.FirstName); 83 | Assert.Equal("O'Connell", target.LastName); 84 | Assert.Equal("Jennifer O'Connell", target.DisplayName); 85 | Assert.Null(target.Title); 86 | } 87 | 88 | [Fact] 89 | public void Parse_FayçalElDASHKhoury() 90 | { 91 | var fullName = "Fayçal El-Khoury"; 92 | var target = new FullNameParser(fullName); 93 | target.Parse(); 94 | 95 | Assert.Equal("Fayçal", target.FirstName); 96 | Assert.Equal("El-Khoury", target.LastName); 97 | Assert.Equal("Fayçal El-Khoury", target.DisplayName); 98 | Assert.Null(target.Title); 99 | } 100 | 101 | [Fact] 102 | public void Parse_HonDOTGinettePetitpasTaylor() 103 | { 104 | var fullName = "Hon. Ginette Petitpas Taylor"; 105 | var target = new FullNameParser(fullName); 106 | target.Parse(); 107 | 108 | Assert.Equal("Hon.", target.Title); 109 | Assert.Equal("Ginette", target.FirstName); 110 | Assert.Equal("Petitpas Taylor", target.LastName); 111 | Assert.Equal("Ginette Petitpas Taylor", target.DisplayName); 112 | 113 | } 114 | 115 | [Fact] 116 | public void Parse_HonDOTDeepakObhrai() 117 | { 118 | var fullName = "Hon. Deepak Obhrai"; 119 | var target = new FullNameParser(fullName); 120 | target.Parse(); 121 | 122 | Assert.Equal("Hon.", target.Title); 123 | Assert.Equal("Deepak", target.FirstName); 124 | Assert.Equal("Obhrai", target.LastName); 125 | Assert.Equal("Deepak Obhrai", target.DisplayName); 126 | 127 | } 128 | 129 | [Fact] 130 | public void Parse_HonDOTJodyWilsonDASHRaybould() 131 | { 132 | var fullName = "Hon. Jody Wilson-Raybould"; 133 | var target = new FullNameParser(fullName); 134 | target.Parse(); 135 | 136 | Assert.Equal("Hon.", target.Title); 137 | Assert.Equal("Jody", target.FirstName); 138 | Assert.Equal("Wilson-Raybould", target.LastName); 139 | Assert.Equal("Jody Wilson-Raybould", target.DisplayName); 140 | 141 | } 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/DataFiles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Xml.Linq; 6 | 7 | 8 | namespace BinaryFog.NameParser.Tests { 9 | public static class DataFiles { 10 | private static readonly string DirectoryPath 11 | = Path.Combine( 12 | Path.GetDirectoryName( 13 | new Uri( 14 | typeof(DataFiles).GetTypeInfo() 15 | .Assembly.CodeBase 16 | ).LocalPath 17 | ), 18 | "DataFiles" 19 | ); 20 | 21 | public static Stream GetStream(string fileName) 22 | => File.OpenRead(Path.Combine(DirectoryPath, fileName)); 23 | 24 | private static ConcurrentDictionary XDocuments { get; } 25 | = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); 26 | 27 | public static XDocument GetXDocument(string fileName) { 28 | if (!XDocuments.TryGetValue(fileName, out var doc)) 29 | using (var stream = GetStream(fileName)) 30 | XDocuments[fileName] = doc = XDocument.Load(stream); 31 | return doc; 32 | } 33 | 34 | public static string GetJsonString(string fileName) 35 | { 36 | using (FileStream fileStream = (FileStream)GetStream(fileName)) 37 | using (StreamReader reader = new StreamReader(fileStream)) 38 | { 39 | return reader.ReadToEnd(); 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/DataFiles/AfricanNames.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Ja'Wuan 5 | James 6 | Ja'Wuan James 7 | 8 | 9 | J'Marcus 10 | Webb 11 | J'Marcus Webb 12 | 13 | 14 | Tre' 15 | Jackson 16 | Tre' Jackson 17 | 18 | 19 | Dont'a 20 | Hightower 21 | Dont'a Hightower 22 | 23 | 24 | D'Qwell 25 | Jackson 26 | D'Qwell Jackson 27 | 28 | 29 | Za'Darius 30 | Smith 31 | Za'Darius Smith 32 | 33 | 34 | De'Ondre 35 | Wesley 36 | De'Ondre Wesley 37 | 38 | 39 | Le'Veon 40 | Bell 41 | Le'Veon Bell 42 | 43 | 44 | Ka'imi 45 | Fairbairn 46 | Ka'imi Fairbairn 47 | 48 | 49 | Xavier 50 | Su'a-Filo 51 | Xavier Su'a-Filo 52 | 53 | 54 | Le'Raven 55 | Clark 56 | Le'Raven Clark 57 | 58 | 59 | D'Joun 60 | Smith 61 | D'Joun Smith 62 | 63 | 64 | Sen'Derrick 65 | Marks 66 | Sen'Derrick Marks 67 | 68 | 69 | Da'Norris 70 | Searcy 71 | Da'Norris Searcy 72 | 73 | 74 | Manti 75 | Te 'o 76 | Manti Te 'o 77 | 78 | 79 | Uani 80 | 'Unga 81 | Uani 'Unga 82 | 83 | 84 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/FullNameParserTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace BinaryFog.NameParser.Tests { 5 | /// 6 | ///This is a test class for FullNameParserTest and is intended 7 | ///to contain all FullNameParserTest Unit Tests 8 | /// 9 | public class FullNameParserTest { 10 | /// 11 | ///A test for Parse 12 | /// 13 | [Fact] 14 | public void Parse_JackJohnson() { 15 | var fullName = "Jack Johnson"; 16 | var target = new FullNameParser(fullName); 17 | target.Parse(); 18 | 19 | Assert.Equal("Jack", target.FirstName); 20 | Assert.Equal("Johnson", target.LastName); 21 | Assert.Equal("Jack Johnson", target.DisplayName); 22 | Assert.Null(target.Title); 23 | } 24 | 25 | [Fact] 26 | public void Parse_MrDotJackJohnson() { 27 | var fullName = "Mr. Jack Johnson"; 28 | var target = new FullNameParser(fullName); 29 | target.Parse(); 30 | 31 | Assert.Equal("Jack", target.FirstName); 32 | Assert.Equal("Johnson", target.LastName); 33 | Assert.Equal("Jack Johnson", target.DisplayName); 34 | Assert.Equal("Mr.", target.Title); 35 | } 36 | 37 | [Fact] 38 | public void Parse_MrJackJohnson() { 39 | var fullName = "Mr Jack Johnson"; 40 | var target = new FullNameParser(fullName); 41 | target.Parse(); 42 | 43 | Assert.Equal("Jack", target.FirstName); 44 | Assert.Equal("Johnson", target.LastName); 45 | Assert.Equal("Jack Johnson", target.DisplayName); 46 | Assert.Equal("Mr", target.Title); 47 | } 48 | 49 | [Fact] 50 | public void Parse_MrJackJohnsonJrDOT() { 51 | var fullName = "Mr Jack Johnson Jr."; 52 | var target = new FullNameParser(fullName); 53 | target.Parse(); 54 | 55 | Assert.Equal("Jack", target.FirstName); 56 | Assert.Equal("Johnson", target.LastName); 57 | Assert.Equal("Jack Johnson", target.DisplayName); 58 | Assert.Equal("Mr", target.Title); 59 | } 60 | 61 | [Fact] 62 | public void Parse_MrJayJPositano() { 63 | var fullName = "Mr Jay J Positano"; 64 | var target = new FullNameParser(fullName); 65 | target.Parse(); 66 | 67 | Assert.Equal("Jay", target.FirstName); 68 | Assert.Equal("Positano", target.LastName); 69 | Assert.Equal("Jay J. Positano", target.DisplayName); 70 | Assert.Equal("Mr", target.Title); 71 | } 72 | 73 | [Fact] 74 | public void Parse_MrJayJDOTPositano() { 75 | var fullName = "Mr Jay J. Positano"; 76 | var target = new FullNameParser(fullName); 77 | target.Parse(); 78 | 79 | Assert.Equal("Mr", target.Title); 80 | Assert.Equal("Jay", target.FirstName); 81 | Assert.Equal("Positano", target.LastName); 82 | Assert.Equal("Jay J. Positano", target.DisplayName); 83 | } 84 | 85 | [Fact] 86 | public void Parse_MrJackJohnsonJr() { 87 | var fullName = "Mr Jack Johnson Jr"; 88 | var target = new FullNameParser(fullName); 89 | target.Parse(); 90 | 91 | Assert.Equal("Mr", target.Title); 92 | Assert.Equal("Jack", target.FirstName); 93 | Assert.Equal("Johnson", target.LastName); 94 | Assert.Equal("Jack Johnson", target.DisplayName); 95 | 96 | } 97 | 98 | [Fact] 99 | public void Parse_JoeSpaceLastmanSpaceJrSpaceEsq() 100 | { 101 | var fullName = "Joe Lastman Jr. Esq."; 102 | var target = new FullNameParser(fullName); 103 | target.Parse(); 104 | 105 | Assert.Equal("Joe", target.FirstName); 106 | Assert.Equal("Lastman", target.LastName); 107 | Assert.Equal("Jr. Esq.", target.Suffix); 108 | Assert.Equal("Joe Lastman", target.DisplayName); 109 | 110 | } 111 | 112 | 113 | [Fact] 114 | public void Parse_AffiliatedForkliftServices() { 115 | var fullName = "AFFILIATED FORKLIFT SERVICES"; 116 | var target = new FullNameParser(fullName); 117 | target.Parse(); 118 | 119 | Assert.Equal("AFFILIATED FORKLIFT SERVICES", target.DisplayName); 120 | Assert.Null(target.FirstName); 121 | Assert.Null(target.LastName); 122 | Assert.Null(target.Title); 123 | Assert.Null(target.NickName); 124 | } 125 | 126 | 127 | [Fact] 128 | public void Parse_AkContractingSCOPEKenoraSCOPELtd() { 129 | var fullName = "AK CONTRACTING (KENORA) LTD."; 130 | var target = new FullNameParser(fullName); 131 | target.Parse(); 132 | 133 | Assert.Equal("AK CONTRACTING (KENORA) LTD.", target.DisplayName); 134 | } 135 | 136 | [Fact] 137 | public void Parse_PasqualeSCOPEPatSCOPEJohnson() { 138 | var fullName = "Pasquale (Pat) Johnson"; 139 | var target = new FullNameParser(fullName); 140 | target.Parse(); 141 | 142 | Assert.Equal("Pasquale", target.FirstName); 143 | Assert.Equal("Johnson", target.LastName); 144 | Assert.Equal("Pasquale Johnson", target.DisplayName); 145 | Assert.Equal("Pat", target.NickName); 146 | } 147 | 148 | [Fact] 149 | public void Parse_MrDOTPasqualeSCOPEPatSCOPEJohnson() { 150 | var fullName = "Mr. Pasquale (Pat) Johnson"; 151 | var target = new FullNameParser(fullName); 152 | target.Parse(); 153 | 154 | Assert.Equal("Mr.", target.Title); 155 | Assert.Equal("Pasquale", target.FirstName); 156 | Assert.Equal("Johnson", target.LastName); 157 | Assert.Equal("Pasquale Johnson", target.DisplayName); 158 | Assert.Equal("Pat", target.NickName); 159 | } 160 | 161 | [Fact] 162 | public void Parse_MrDOTPasqualeSCOPEPatSCOPEJohnsonJr() { 163 | var fullName = "Mr. Pasquale (Pat) Johnson Jr"; 164 | var target = new FullNameParser(fullName); 165 | target.Parse(); 166 | 167 | Assert.Equal("Mr.", target.Title); 168 | Assert.Equal("Pasquale", target.FirstName); 169 | Assert.Equal("Johnson", target.LastName); 170 | Assert.Equal("Pasquale Johnson", target.DisplayName); 171 | Assert.Equal("Pat", target.NickName); 172 | Assert.Equal("Jr", target.Suffix); 173 | } 174 | 175 | [Fact] 176 | public void Parse_CompanyNamesAsPersonNames() { 177 | string[] companyNamesAsPersonNames = { 178 | //"AL HUGHES (MARINE)", => AL HUGHES 179 | "HI TECH HYDRAULICS (1985) LT", 180 | "ALFALFA BEEKEEPERS LTD", 181 | //"ALAA SALAH AELSAYAD@TORCC.", => ALAA SALAH AELSAYAD 182 | }; 183 | 184 | foreach (var item in companyNamesAsPersonNames) { 185 | //Console.WriteLine(item); 186 | var fullName = item; 187 | var target = new FullNameParser(fullName); 188 | target.Parse(); 189 | 190 | Assert.Equal(fullName, target.DisplayName); 191 | Assert.Null(target.FirstName); 192 | Assert.Null(target.LastName); 193 | Assert.Null(target.Title); 194 | Assert.Null(target.NickName); 195 | } 196 | } 197 | 198 | 199 | [Fact] 200 | public void Parse_ATTNMrEricKing() { 201 | var fullName = "ATTN: MR. ERIC KING"; 202 | var target = new FullNameParser(fullName); 203 | target.Parse(); 204 | 205 | Assert.Equal("ERIC KING", target.DisplayName); 206 | Assert.Equal("ERIC", target.FirstName); 207 | Assert.Equal("KING", target.LastName); 208 | Assert.Equal("MR.", target.Title); 209 | } 210 | 211 | [Fact] 212 | public void Parse_Catalin() { 213 | var fullName = "Catalin"; 214 | var target = new FullNameParser(fullName); 215 | target.Parse(); 216 | 217 | Assert.Equal("Catalin", target.FirstName); 218 | } 219 | 220 | [Fact] 221 | public void Parse_Arroyo() { 222 | var fullName = "Arroyo"; 223 | var target = new FullNameParser(fullName); 224 | target.Parse(); 225 | 226 | Assert.Equal("Arroyo", target.LastName); 227 | } 228 | 229 | [Fact] 230 | public void Parse_MrGiocomoVanExan() { 231 | var fullName = "Mr Giocomo Van Exan"; 232 | var target = new FullNameParser(fullName); 233 | target.Parse(); 234 | 235 | Assert.Equal("Mr", target.Title); 236 | Assert.Equal("Giocomo", target.FirstName); 237 | Assert.Equal("Van Exan", target.LastName); 238 | } 239 | 240 | [Fact] 241 | public void Parse_GiovanniVanDerHutte() { 242 | var fullName = "Giovanni Van Der Hutte"; 243 | var target = new FullNameParser(fullName); 244 | target.Parse(); 245 | 246 | Assert.Equal("Giovanni", target.FirstName); 247 | Assert.Equal("Van Der Hutte", target.LastName); 248 | } 249 | 250 | [Fact] 251 | public void Parse_MsSandyAccountsReceivable() { 252 | var fullName = "Ms Sandy Accounts Receivable"; 253 | var target = new FullNameParser(fullName); 254 | target.Parse(); 255 | 256 | Assert.Equal("Ms", target.Title); 257 | Assert.Equal("Sandy", target.FirstName); 258 | Assert.Equal("Sandy Accounts Receivable", target.DisplayName); 259 | } 260 | 261 | [Fact] 262 | public void Parse_SandyAccountsReceivable() { 263 | var fullName = "Sandy Accounts Receivable"; 264 | var target = new FullNameParser(fullName); 265 | target.Parse(); 266 | 267 | Assert.Equal("Sandy", target.FirstName); 268 | } 269 | 270 | [Fact] 271 | public void Parse_MrJackFrancisVanDerWaalSr() { 272 | var fullName = "Mr. Jack Francis Van Der Waal Sr."; 273 | var target = new FullNameParser(fullName); 274 | target.Parse(); 275 | 276 | Assert.Equal("Mr.", target.Title); 277 | Assert.Equal("Jack", target.FirstName); 278 | Assert.Equal("Francis", target.MiddleName); 279 | Assert.Equal("Van Der Waal", target.LastName); 280 | Assert.Equal("Sr.", target.Suffix); 281 | Assert.Equal("Jack Francis Van Der Waal", target.DisplayName); 282 | } 283 | 284 | [Fact] 285 | public void Parse_MrJackFrancisMarionVanDerWaalSr() { 286 | var fullName = "Mr. Jack Francis Marion Van Der Waal Sr."; 287 | var target = new FullNameParser(fullName); 288 | target.Parse(); 289 | 290 | Assert.Equal("Mr.", target.Title); 291 | Assert.Equal("Jack", target.FirstName); 292 | Assert.Equal("Francis Marion", target.MiddleName); 293 | Assert.Equal("Van Der Waal", target.LastName); 294 | Assert.Equal("Sr.", target.Suffix); 295 | } 296 | 297 | 298 | [Fact] 299 | public void Parse_Null() { 300 | string fullName = null; 301 | // ReSharper disable once ExpressionIsAlwaysNull 302 | var target = new FullNameParser(fullName); 303 | target.Parse(); 304 | 305 | Assert.Null(target.Title); 306 | Assert.Null(target.FirstName); 307 | Assert.Null(target.MiddleName); 308 | Assert.Null(target.LastName); 309 | Assert.Null(target.Suffix); 310 | } 311 | 312 | 313 | [Fact] 314 | public void Parse_Blank() { 315 | var fullName = ""; 316 | var target = new FullNameParser(fullName); 317 | target.Parse(); 318 | 319 | Assert.Null(target.Title); 320 | Assert.Null(target.FirstName); 321 | Assert.Null(target.MiddleName); 322 | Assert.Null(target.LastName); 323 | Assert.Null(target.Suffix); 324 | } 325 | 326 | 327 | [Fact] 328 | public void Parse_Space() { 329 | var fullName = " "; 330 | var target = new FullNameParser(fullName); 331 | target.Parse(); 332 | 333 | Assert.Null(target.Title); 334 | Assert.Null(target.FirstName); 335 | Assert.Null(target.MiddleName); 336 | Assert.Null(target.LastName); 337 | Assert.Null(target.Suffix); 338 | } 339 | 340 | [Fact] 341 | public void Parse_Static() { 342 | var fullName = ""; 343 | var target = FullNameParser.Parse(fullName); 344 | 345 | Assert.NotNull(target); 346 | } 347 | } 348 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/InitialAsMiddleNameTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Xunit; 4 | 5 | namespace BinaryFog.NameParser.Tests { 6 | 7 | 8 | /// 9 | ///This is a test class for FullNameParserTest and is intended 10 | ///to contain all FullNameParserTest Unit Tests 11 | /// 12 | public class InitialAsMiddleNameTests 13 | { 14 | [Fact] 15 | public void Parse_MrJonADOTvanderWaalJr() { 16 | var fullName = "Mr. Jon A. van der Waal Jr."; 17 | var target = new FullNameParser(fullName); 18 | target.Parse(); 19 | 20 | Assert.Equal("Jon", target.FirstName); 21 | Assert.Equal("van der Waal", target.LastName); 22 | Assert.Equal("A.", target.MiddleName); 23 | Assert.Equal("Mr.", target.Title); 24 | Assert.Equal("Jr.", target.Suffix); 25 | 26 | } 27 | 28 | [Fact] 29 | public void Parse_MrJonADOTWaalJr() 30 | { 31 | var fullName = "Mr. Jon A. Waal Jr."; 32 | var target = new FullNameParser(fullName); 33 | target.Parse(); 34 | 35 | Assert.Equal("Jon", target.FirstName); 36 | Assert.Equal("Waal", target.LastName); 37 | Assert.Equal("A.", target.MiddleName); 38 | Assert.Equal("Mr.", target.Title); 39 | Assert.Equal("Jr.", target.Suffix); 40 | 41 | } 42 | 43 | [Fact] 44 | public void Parse_JonADOTvanderWaalJr() 45 | { 46 | var fullName = "Jon A. van der Waal Jr."; 47 | var target = new FullNameParser(fullName); 48 | target.Parse(); 49 | 50 | Assert.Equal("Jon", target.FirstName); 51 | Assert.Equal("van der Waal", target.LastName); 52 | Assert.Equal("A.", target.MiddleName); 53 | Assert.Equal("Jr.", target.Suffix); 54 | 55 | } 56 | 57 | [Fact] 58 | public void Parse_JonADOTWaalJr() 59 | { 60 | var fullName = "Jon A. Waal Jr."; 61 | var target = new FullNameParser(fullName); 62 | target.Parse(); 63 | 64 | Assert.Equal("Jon", target.FirstName); 65 | Assert.Equal("Waal", target.LastName); 66 | Assert.Equal("A.", target.MiddleName); 67 | Assert.Equal("Jr.", target.Suffix); 68 | 69 | } 70 | 71 | [Fact] 72 | public void Parse_JamesAAdams() 73 | { 74 | var fullName = "James A Adams"; 75 | var target = new FullNameParser(fullName); 76 | target.Parse(); 77 | 78 | Assert.Equal("James", target.FirstName); 79 | Assert.Equal("A Adams", target.LastName); 80 | 81 | } 82 | 83 | [Fact] 84 | public void Parse_JamesADOTAdams() 85 | { 86 | var fullName = "James A. Adams"; 87 | var target = new FullNameParser(fullName); 88 | target.Parse(); 89 | 90 | Assert.Equal("James", target.FirstName); 91 | Assert.Equal("Adams", target.LastName); 92 | Assert.Equal("A.", target.MiddleName); 93 | } 94 | 95 | 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/MGuinessParserTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Xunit; 4 | 5 | namespace BinaryFog.NameParser.Tests { 6 | 7 | 8 | /// 9 | ///This is a test class for FullNameParserTest and is intended 10 | ///to contain all FullNameParserTest Unit Tests 11 | /// 12 | public class MGuinessParserTests 13 | { 14 | //Unit test suggested by mguiness 15 | [Fact] 16 | public void Parse_JohnTDOTHancockCommaSpaceJr() 17 | { 18 | var fullName = "John T. Hancock, Jr."; 19 | var target = new FullNameParser(fullName); 20 | target.Parse(); 21 | 22 | Assert.Equal("John", target.FirstName); 23 | Assert.Equal("Hancock", target.LastName); 24 | Assert.Equal("T.", target.MiddleName); 25 | Assert.Equal("Jr.", target.Suffix); 26 | Assert.Equal("John T. Hancock", target.DisplayName); 27 | 28 | } 29 | 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/MattGilletesParserTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Xunit; 4 | 5 | namespace BinaryFog.NameParser.Tests { 6 | 7 | 8 | /// 9 | ///This is a test class for FullNameParserTest and is intended 10 | ///to contain all FullNameParserTest Unit Tests 11 | /// 12 | public class MattGilletesParserTests 13 | { 14 | [Fact] 15 | public void Parse_IfoEkpreDASHOlomu() { 16 | var fullName = "Ifo Ekpre-Olomu"; 17 | var target = new FullNameParser(fullName); 18 | target.Parse(); 19 | 20 | Assert.Equal("Ifo", target.FirstName); 21 | Assert.Equal("Ekpre-Olomu", target.LastName); 22 | Assert.Equal("Ifo Ekpre-Olomu", target.DisplayName); 23 | 24 | } 25 | 26 | [Fact] 27 | public void Parse_IsaAbdulDASHQuddus() 28 | { 29 | var fullName = "Isa Abdul-Quddus"; 30 | var target = new FullNameParser(fullName); 31 | target.Parse(); 32 | 33 | Assert.Equal("Isa", target.FirstName); 34 | Assert.Equal("Abdul-Quddus", target.LastName); 35 | Assert.Equal("Isa Abdul-Quddus", target.DisplayName); 36 | 37 | } 38 | 39 | [Fact] 40 | public void Parse_EDOTJDOTSPACEManuel() 41 | { 42 | var fullName = "E.J. Manuel"; 43 | var target = new FullNameParser(fullName); 44 | target.Parse(); 45 | 46 | Assert.Equal("E.", target.FirstName); 47 | Assert.Equal("J.", target.MiddleName); 48 | Assert.Equal("Manuel", target.LastName); 49 | Assert.Equal("E. J. Manuel", target.DisplayName); 50 | 51 | } 52 | 53 | [Fact] 54 | public void Parse_DDOTSpaceJDotSpaceFoster() 55 | { 56 | var fullName = "D. J. Foster"; 57 | var target = new FullNameParser(fullName); 58 | target.Parse(); 59 | 60 | Assert.Equal("D.", target.FirstName); 61 | Assert.Equal("J.", target.MiddleName); 62 | Assert.Equal("Foster", target.LastName); 63 | Assert.Equal("D. J. Foster", target.DisplayName); 64 | 65 | } 66 | 67 | [Fact] 68 | public void Parse_AlDASHHajjSPACEShabazz() 69 | { 70 | var fullName = "Al-Hajj Shabazz"; 71 | var target = new FullNameParser(fullName); 72 | target.Parse(); 73 | 74 | Assert.Equal("Al-Hajj", target.FirstName); 75 | Assert.Equal("Shabazz", target.LastName); 76 | Assert.Equal("Al-Hajj Shabazz", target.DisplayName); 77 | 78 | } 79 | 80 | [Fact] 81 | public void Parse_DeAndreHoustonDASHCarson() 82 | { 83 | var fullName = "DeAndre Houston-Carson"; 84 | var target = new FullNameParser(fullName); 85 | target.Parse(); 86 | 87 | Assert.Equal("DeAndre", target.FirstName); 88 | Assert.Equal("Houston-Carson", target.LastName); 89 | Assert.Equal("DeAndre Houston-Carson", target.DisplayName); 90 | 91 | } 92 | 93 | [Fact] 94 | public void Parse_CDOTSpaceJSpaceFoster() 95 | { 96 | var fullName = "C. J Smith"; 97 | var target = new FullNameParser(fullName); 98 | target.Parse(); 99 | 100 | Assert.Equal("C.", target.FirstName); 101 | Assert.Equal("J.", target.MiddleName); 102 | Assert.Equal("Smith", target.LastName); 103 | Assert.Equal("C. J. Smith", target.DisplayName); 104 | 105 | } 106 | 107 | [Fact] 108 | public void Parse_CDOTJDOTSpaceFosterIII() 109 | { 110 | var fullName = "C.J. Foster III"; 111 | var target = new FullNameParser(fullName); 112 | target.Parse(); 113 | 114 | Assert.Equal("C.", target.FirstName); 115 | Assert.Equal("J.", target.MiddleName); 116 | Assert.Equal("Foster", target.LastName); 117 | Assert.Equal("III", target.Suffix); 118 | Assert.Equal("C. J. Foster", target.DisplayName); 119 | 120 | } 121 | 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/PFornessParserTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Xunit; 4 | 5 | namespace BinaryFog.NameParser.Tests { 6 | 7 | 8 | /// 9 | ///This is a test class for FullNameParserTest and is intended 10 | ///to contain all FullNameParserTest Unit Tests 11 | /// 12 | public class PFornessParserTests 13 | { 14 | //Unit test suggested by pforness 15 | [Fact] 16 | public void Parse_FornessCommaPaulSpaceTDot() 17 | { 18 | var fullName = "Forness, Paul T."; 19 | var target = new FullNameParser(fullName); 20 | target.Parse(); 21 | 22 | Assert.Equal("Paul", target.FirstName); 23 | Assert.Equal("Forness", target.LastName); 24 | Assert.Equal("T", target.MiddleName); 25 | Assert.Equal("Paul T. Forness", target.DisplayName); 26 | 27 | } 28 | 29 | 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/RandomNamesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using RandomNameGeneratorLibrary; 6 | using Xunit; 7 | 8 | namespace BinaryFog.NameParser.Tests { 9 | public class RandomNamesTests { 10 | /* There are names like "Miss", and "Lady" in the female first names generated... 11 | private static PersonNameGenerator NameGen { get; } 12 | = new PersonNameGenerator(); 13 | 14 | private static RandomNumberGenerator Rng { get; } 15 | = RandomNumberGenerator.Create(); 16 | 17 | public static IEnumerable GetSimpleRandomNames(int count) { 18 | var randomBytes = new byte[count]; 19 | Rng.GetBytes(randomBytes); 20 | 21 | for (var i = 0 ; i < count ; ++i) { 22 | var randomBit1 = (randomBytes[i] & (1 << 0)) != 0; 23 | var randomBit2 = (randomBytes[i] & (1 << 1)) != 0; 24 | var randomBit3 = (randomBytes[i] & (1 << 2)) != 0; 25 | var randomBit4 = (randomBytes[i] & (1 << 3)) != 0; 26 | var randomBit5 = (randomBytes[i] & (1 << 4)) != 0; 27 | var randomBit6 = (randomBytes[i] & (1 << 5)) != 0; 28 | var nameCount = 1 + ((randomBytes[i] & (3 << 6)) >> 6); // 1 to 4 nameParts 29 | 30 | 31 | var nameParts = new string[nameCount]; 32 | 33 | 34 | var gender = randomBit1; 35 | nameParts[0] = gender 36 | ? NameGen.GenerateRandomMaleFirstName() 37 | : NameGen.GenerateRandomFemaleFirstName(); 38 | 39 | if (nameParts.Length > 2) { 40 | nameParts[1] = randomBit2 41 | ? ( gender 42 | ? NameGen.GenerateRandomMaleFirstName() 43 | : NameGen.GenerateRandomFemaleFirstName() ) 44 | : NameGen.GenerateRandomLastName(); 45 | if (randomBit6) 46 | nameParts[1] = $@"""{nameParts[1]}"""; 47 | } 48 | 49 | 50 | if (nameParts.Length > 3) 51 | nameParts[2] = randomBit3 52 | ? ( gender 53 | ? NameGen.GenerateRandomMaleFirstName() 54 | : NameGen.GenerateRandomFemaleFirstName() ) 55 | : NameGen.GenerateRandomLastName(); 56 | 57 | if (nameParts.Length > 1 || randomBit5 && nameParts.Length == 1) 58 | nameParts[nameParts.Length - 1] = 59 | randomBit4 60 | ? NameGen.GenerateRandomLastName() 61 | : NameGen.GenerateRandomLastName() + "-" + NameGen.GenerateRandomLastName(); 62 | 63 | yield return new object[] { 64 | nameParts 65 | }; 66 | } 67 | } 68 | 69 | [Theory] 70 | [MemberData(nameof(GetSimpleRandomNames), 400, DisableDiscoveryEnumeration = true)] 71 | public void SimpleRandomNamesTest(string[] nameParts) { 72 | var firstName = nameParts[0]; 73 | var singleName = nameParts.Length == 1; 74 | var lastName = singleName ? null : nameParts[nameParts.Length - 1]; 75 | var fullName = string.Join(" ", nameParts.Where(s => s[0] != '"')); 76 | //Console.WriteLine(fullName); 77 | 78 | var target = new FullNameParser(fullName); 79 | target.Parse(); 80 | 81 | if (singleName) { 82 | if (target.FirstName == null) { 83 | //Assert.Null(target.FirstName); 84 | Assert.Equal(firstName, target.LastName); 85 | } 86 | else { 87 | Assert.Equal(firstName, target.FirstName); 88 | Assert.Null(target.LastName); 89 | } 90 | Assert.Equal(firstName, target.DisplayName); 91 | } 92 | else { 93 | Assert.Equal(firstName, target.FirstName); 94 | if (target.LastName.Contains(" ")) { 95 | lastName = string.Join(" ", nameParts[nameParts.Length - 2], lastName); 96 | } 97 | 98 | Assert.Equal(lastName, target.LastName); 99 | 100 | Assert.Equal(fullName, target.DisplayName); 101 | } 102 | } 103 | 104 | 105 | public static IEnumerable GetTitledRandomNames(int count) { 106 | var randomBytes = new byte[count]; 107 | Rng.GetBytes(randomBytes); 108 | 109 | for (var i = 0 ; i < count ; ++i) { 110 | var randomBit1 = (randomBytes[i] & (1 << 0)) != 0; 111 | var randomBit2 = (randomBytes[i] & (1 << 1)) != 0; 112 | var randomBit3 = (randomBytes[i] & (1 << 2)) != 0; 113 | var randomBit4 = (randomBytes[i] & (1 << 3)) != 0; 114 | var randomBit5 = (randomBytes[i] & (1 << 4)) != 0; 115 | var randomBit6 = (randomBytes[i] & (1 << 5)) != 0; 116 | var nameCount = 1 + ((randomBytes[i] & (3 << 6)) >> 6); // 1 to 4 nameParts 117 | 118 | 119 | var nameParts = new string[nameCount+1]; 120 | 121 | 122 | var gender = randomBit1; 123 | 124 | nameParts[0] = randomBit3 125 | ? "Dr." 126 | : gender 127 | ? "Mr." 128 | : randomBit4 129 | ? "Ms." 130 | : "Mrs."; 131 | if (randomBit5) 132 | nameParts[0] = nameParts[0].Replace(".", ""); 133 | 134 | nameParts[1] = gender 135 | ? NameGen.GenerateRandomMaleFirstName() 136 | : NameGen.GenerateRandomFemaleFirstName(); 137 | 138 | if (nameParts.Length > 3) { 139 | nameParts[2] = randomBit2 140 | ? ( gender 141 | ? NameGen.GenerateRandomMaleFirstName() 142 | : NameGen.GenerateRandomFemaleFirstName() ) 143 | : NameGen.GenerateRandomLastName(); 144 | if (randomBit6) 145 | nameParts[2] = $@"""{nameParts[2]}"""; 146 | } 147 | 148 | if (nameParts.Length > 4) 149 | nameParts[3] = randomBit3 150 | ? ( gender 151 | ? NameGen.GenerateRandomMaleFirstName() 152 | : NameGen.GenerateRandomFemaleFirstName() ) 153 | : NameGen.GenerateRandomLastName(); 154 | 155 | if (nameParts.Length > 1 || randomBit5 && nameParts.Length == 1) 156 | nameParts[nameParts.Length - 1] = 157 | randomBit4 158 | ? NameGen.GenerateRandomLastName() 159 | : NameGen.GenerateRandomLastName() + "-" + NameGen.GenerateRandomLastName(); 160 | 161 | yield return new object[] { 162 | nameParts.Where(namePart => namePart != null).ToArray() 163 | }; 164 | } 165 | } 166 | 167 | [Theory] 168 | [MemberData(nameof(GetTitledRandomNames), 400, DisableDiscoveryEnumeration = true)] 169 | public void TitledRandomNamesTest(string[] nameParts) { 170 | var firstName = nameParts[1]; 171 | var singleName = nameParts.Length == 2; 172 | var lastName = singleName ? null : nameParts[nameParts.Length - 1]; 173 | var fullName = string.Join(" ", nameParts.Skip(1).Where(s => s[0] != '"')); 174 | //Console.WriteLine(fullName); 175 | 176 | var target = new FullNameParser(fullName); 177 | target.Parse(); 178 | 179 | if (singleName) { 180 | if (target.FirstName == null) { 181 | //Assert.Null(target.FirstName); 182 | Assert.Equal(firstName, target.LastName); 183 | } 184 | else { 185 | Assert.Equal(firstName, target.FirstName); 186 | Assert.Null(target.LastName); 187 | } 188 | Assert.Equal(firstName, target.DisplayName); 189 | } 190 | else { 191 | Assert.Equal(firstName, target.FirstName); 192 | if (target.LastName.Contains(" ")) { 193 | lastName = string.Join(" ", nameParts[nameParts.Length - 2], lastName); 194 | } 195 | 196 | Assert.Equal(lastName, target.LastName); 197 | 198 | Assert.Equal(fullName, target.DisplayName); 199 | } 200 | } 201 | */ 202 | } 203 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/TestFullNamePattern.cs: -------------------------------------------------------------------------------- 1 | namespace BinaryFog.NameParser.Tests { 2 | public class TestFullNamePattern : IFullNamePattern { 3 | public ParsedFullName Parse(string rawName) 4 | => rawName == "EXAMPLE" 5 | ? new ParsedFullName { 6 | FirstName = "Success", 7 | LastName = "Success", 8 | MiddleName = "Success", 9 | DisplayName = "Success", 10 | Suffix = "Success", 11 | NickName = "Success", 12 | Title = "Success", 13 | Score = int.MaxValue 14 | } 15 | : null; 16 | } 17 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/ThirdPartyIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace BinaryFog.NameParser.Tests { 7 | public class ThirdPartyIntegrationTests { 8 | [Fact] 9 | public void FirstMiddlePrefixedLastSuffix() { 10 | var fullName = "EXAMPLE"; 11 | var target = new FullNameParser(fullName); 12 | 13 | Assert.False(FullNameParser.EnableAutomaticThirdPartyIntegration); 14 | 15 | target.Parse(); 16 | 17 | Assert.Equal("EXAMPLE", target.FirstName); 18 | Assert.Null(target.LastName); 19 | Assert.Equal("EXAMPLE", target.DisplayName); 20 | 21 | FullNameParser.EnableAutomaticThirdPartyIntegration = true; 22 | 23 | target.Parse(); 24 | 25 | Assert.Equal("Success", target.FirstName); 26 | Assert.Equal("Success", target.LastName); 27 | Assert.Equal("Success", target.DisplayName); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/USRepresentativesTests.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using Xunit; 6 | 7 | 8 | namespace BinaryFog.NameParser.Tests 9 | { 10 | public class USRepresentativesTests 11 | { 12 | 13 | public static IEnumerable GetUSRepresentatives() 14 | { 15 | var j = JObject.Parse(DataFiles.GetJsonString("USRepresentatives.json")!); 16 | 17 | return (j["objects"]! 18 | .Select(e => new object[] 19 | { 20 | e["person"]?["firstname"]?.ToString(), 21 | e["person"]?["lastname"]?.ToString(), 22 | e["person"]?["name"]?.ToString(), 23 | e["person"]?["nickname"]?.ToString(), 24 | })).ToArray(); 25 | } 26 | 27 | [Theory] 28 | [MemberData(nameof(GetUSRepresentatives),DisableDiscoveryEnumeration = true)] 29 | public void GetUSRepresentatives_Test(string firstName, string lastName, string name, string nickname) 30 | { 31 | //ARRANGE 32 | //Remove party suffix 33 | Debug.Assert(name != null, nameof(name) + " != null"); 34 | var i = name.IndexOf('['); 35 | var nameWithoutParty = name.Substring(0, i).Trim(); 36 | 37 | //ACT 38 | var target = new FullNameParser(nameWithoutParty); 39 | target.Parse(); 40 | 41 | //ASSERT 42 | Assert.Equal( firstName, target.FirstName); 43 | Assert.Equal( lastName, target.LastName); 44 | 45 | if( lastName == "González-Colón") 46 | Assert.Equal("Commish.", target.Title); 47 | else 48 | Assert.Equal("Rep.", target.Title); 49 | 50 | if (string.IsNullOrEmpty( nickname )) 51 | Assert.Null(target.NickName); 52 | else 53 | Assert.Equal(nickname, target.NickName); 54 | } 55 | 56 | [Fact(Skip ="Pattern for nicknames with commas inside them needs to be added.")] 57 | public void Parse_GeorgeButterfield() 58 | { 59 | var fullName = "Rep. George “G.K.” Butterfield"; 60 | var target = new FullNameParser(fullName); 61 | target.Parse(); 62 | 63 | Assert.Equal("George", target.FirstName); 64 | Assert.Equal("Butterfield", target.LastName); 65 | Assert.Equal("George Butterfield", target.DisplayName); 66 | Assert.Equal("Rep.", target.Title); 67 | Assert.Equal("G.K.", target.NickName); 68 | } 69 | 70 | 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.Tests/USSenatorsTests.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using Xunit; 7 | 8 | 9 | namespace BinaryFog.NameParser.Tests 10 | { 11 | public class USSenatorsTests 12 | { 13 | 14 | public static IEnumerable GetUSSenators() 15 | { 16 | var j = JObject.Parse(DataFiles.GetJsonString("USSenators.json")); 17 | 18 | return ( from e in j["objects"] 19 | select new object[] 20 | { 21 | e["person"]["firstname"].ToString(), 22 | e["person"]["lastname"].ToString(), 23 | e["person"]["name"].ToString(), 24 | e["person"]["nickname"].ToString(), 25 | }).ToArray(); 26 | } 27 | 28 | [Theory] 29 | [MemberData(nameof(GetUSSenators),DisableDiscoveryEnumeration = true)] 30 | public void GetUSSenators_Test( string firstName, string lastName, string name, string nickname) 31 | { 32 | //ARRANGE 33 | //Remove party suffix 34 | int i = name.IndexOf('['); 35 | string nameWithoutParty = name.Substring(0, i).Trim(); 36 | 37 | //ACT 38 | var target = new FullNameParser(nameWithoutParty); 39 | target.Parse(); 40 | 41 | //ASSERT 42 | Assert.Equal( firstName, target.FirstName); 43 | Assert.Equal( lastName, target.LastName); 44 | Assert.Equal("Sen.", target.Title); 45 | if (String.IsNullOrEmpty( nickname )) 46 | Assert.Null(target.NickName); 47 | else 48 | Assert.Equal(nickname, target.NickName); 49 | } 50 | 51 | [Fact] 52 | public void Parse_TammyBaldwin() 53 | { 54 | var fullName = "Sen Tammy Baldwin"; 55 | var target = new FullNameParser(fullName); 56 | target.Parse(); 57 | 58 | Assert.Equal("Tammy", target.FirstName); 59 | Assert.Equal("Baldwin", target.LastName); 60 | Assert.Equal("Tammy Baldwin", target.DisplayName); 61 | Assert.Equal("Sen", target.Title); 62 | } 63 | 64 | 65 | [Fact] 66 | public void Parse_BernieSanders() 67 | { 68 | var fullName = "Sen. Bernard “Bernie” Sanders"; 69 | var target = new FullNameParser(fullName); 70 | target.Parse(); 71 | 72 | Assert.Equal("Bernard", target.FirstName); 73 | Assert.Equal("Sanders", target.LastName); 74 | Assert.Equal("Bernard Sanders", target.DisplayName); 75 | Assert.Equal("Sen.", target.Title); 76 | Assert.Equal("Bernie", target.NickName); 77 | } 78 | 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryFog.NameParser", "BinaryFog.NameParser\BinaryFog.NameParser.csproj", "{5BCB7AA3-D399-4246-A8B9-E88F1FB15465}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryFog.NameParser.Tests", "BinaryFog.NameParser.Tests\BinaryFog.NameParser.Tests.csproj", "{2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug Patterns|Any CPU = Debug Patterns|Any CPU 13 | Debug|Any CPU = Debug|Any CPU 14 | Release|Any CPU = Release|Any CPU 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Debug Patterns|Any CPU.ActiveCfg = Debug|Any CPU 18 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Debug Patterns|Any CPU.Build.0 = Debug|Any CPU 19 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {5BCB7AA3-D399-4246-A8B9-E88F1FB15465}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Debug Patterns|Any CPU.ActiveCfg = Debug|Any CPU 24 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Debug Patterns|Any CPU.Build.0 = Debug|Any CPU 25 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {2D16C3D8-4EC7-4BE4-A991-BF4F85BF54F7}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {3E52C156-A5E3-4F7F-BFA2-AABB181FFC66} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /BinaryFog.NameParser.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | <data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="BinaryFog.NameParser.Tests" ModuleVersionMask="*" ClassMask="AutoGeneratedProgram" FunctionMask="*" IsEnabled="True" /><Filter ModuleMask="BinaryFog.NameParser" ModuleVersionMask="*" ClassMask="BinaryFog.NameParser.ParsedFullName" FunctionMask="Pattern" IsEnabled="True" /><Filter ModuleMask="BinaryFog.NameParser" ModuleVersionMask="*" ClassMask="BinaryFog.NameParser.ParsedFullName" FunctionMask="*_DebuggerDisplay" IsEnabled="True" /><Filter ModuleMask="BinaryFog.NameParser" ModuleVersionMask="*" ClassMask="BinaryFog.NameParser.AssemblyComparer" FunctionMask="Compare" IsEnabled="True" /></ExcludeFilters></data> -------------------------------------------------------------------------------- /BinaryFog.NameParser.sln.GhostDoc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | *.min.js 4 | jquery*.js 5 | 6 | 7 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/BinaryFog.NameParser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | BinaryFog.com 6 | BinaryFog 7 | BinaryFog.NameParser 8 | 9 | Human name parsing. 10 | Parses names using English conventions for persons names. 11 | Many thanks to Tyler Young, Matt Gillette, mguiness,Paul Forness, Jamin Quimby 12 | 13 | Human name parsing. 14 | Parses names using English conventions for persons names. 15 | Many thanks to Tyler Young, Matt Gillette, mguiness,Paul Forness, Jamin Quimby 16 | Copyright © BinaryFog.com 2015 - 2021 17 | 3.2.4 18 | True 19 | https://github.com/binaryfog/NameParser 20 | https://github.com/binaryfog/NameParser 21 | Git 22 | 23 | 24 | 25 | 26 | 27 | TRACE;DEBUG;DEBUG_FULL_NAME_PATTERN_RESULTS 28 | 29 | 30 | 31 | false 32 | 33 | 34 | ..\..\BenefitAgent\src\key.pfx 35 | Added patterns: 36 | Two Hyphen Optionally Spaced Middle pattern 37 | Name parser, name parsing 38 | 3.2.4.0 39 | 3.2.4.0 40 | LICENSE 41 | 999230.jpg 42 | 43 | README.md 44 | 45 | 46 | DEBUG;TRACE;DEBUG_FULL_NAME_PATTERN_RESULTS 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | All 63 | 64 | 65 | All 66 | 67 | 68 | All 69 | 70 | 71 | All 72 | 73 | 74 | All 75 | 76 | 77 | All 78 | 79 | 80 | All 81 | 82 | 83 | All 84 | 85 | 86 | All 87 | 88 | 89 | All 90 | 91 | 92 | All 93 | 94 | 95 | All 96 | 97 | 98 | All 99 | 100 | 101 | 102 | 103 | 104 | True 105 | 106 | 107 | 108 | True 109 | \ 110 | 111 | 112 | True 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/ExcludeFromCodeCoverageAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BinaryFog.NameParser { 4 | [AttributeUsage(AttributeTargets.All,Inherited = false)] 5 | internal class ExcludeFromCodeCoverageAttribute : Attribute { 6 | } 7 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/FullNameParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Linq; 5 | using System.Reflection; 6 | using JetBrains.Annotations; 7 | 8 | namespace BinaryFog.NameParser 9 | { 10 | using static Helpers; 11 | 12 | /// 13 | /// Parse a person full name 14 | /// 15 | /// 16 | /// 1. Mr Jack Johnson => Title = "Mr", First Name = "Jack" Last Name = "Johnson" 17 | /// 2. Jack Johnson => First Name = "Jack" Last Name = "Johnson" 18 | /// 3. Jack => First Name = "Jack" 19 | /// 4. Jack Johnson Enterprises => ignored 20 | /// 5. Pasquale (Pat) Vacoturo => First Name = "Pasquale" Last Name = "Vacoturo" Nickname = Pat 21 | /// 6. Mr Giovanni Van Der Hutte => Title = "Mr", First Name = "Giovanni" Last Name = "Van Der Hutte" 22 | /// 7. Giovanni Van Der Hutte => First Name = "Giovanni" Last Name = "Van Der Hutte" 23 | /// 24 | /// 25 | /// 1. The prefix "ATTN:" is removed if exists and the parsing proceeds on the new string 26 | /// 27 | public class FullNameParser 28 | { 29 | private static bool _enableThirdParty; 30 | 31 | static FullNameParser() 32 | { 33 | BuildPatternsMap(); 34 | } 35 | 36 | /// 37 | /// Initializes a new instance of the class. 38 | /// 39 | /// The full name. 40 | public FullNameParser(string fullName) 41 | { 42 | FullName = fullName; 43 | } 44 | 45 | public IReadOnlyList Results { get; set; } = Array.Empty(); 46 | 47 | protected string FullName { get; private set; } 48 | 49 | protected static Type PatternType { get; } = typeof(IFullNamePattern); 50 | 51 | [UsedImplicitly] 52 | public static bool EnableAutomaticThirdPartyIntegration 53 | { 54 | get => _enableThirdParty; 55 | set 56 | { 57 | _enableThirdParty = value; 58 | BuildPatternsMap(); 59 | } 60 | } 61 | 62 | protected static IEnumerable PatternsMap { get; private set; } 63 | 64 | 65 | public string FirstName { get; private set; } 66 | public string MiddleName { get; private set; } 67 | public string LastName { get; private set; } 68 | public string Title { get; private set; } 69 | public string NickName { get; private set; } 70 | public string Suffix { get; private set; } 71 | public string DisplayName { get; private set; } 72 | 73 | private static void BuildPatternsMap() 74 | { 75 | PatternsMap = (_enableThirdParty 76 | ? KnownAssemblies 77 | .Where(a 78 | => !a.FullName.StartsWith("System.") 79 | && !a.FullName.StartsWith("Microsoft.")) 80 | .SelectMany(s => TryOrDefault(s.GetExportedTypes, Type.EmptyTypes)) 81 | : typeof(FullNameParser).GetTypeInfo().Assembly.GetExportedTypes() 82 | ) 83 | .Where(p => PatternType.IsAssignableFrom(p)) 84 | .Select(t => t.GetConstructor(Type.EmptyTypes)?.Invoke(null)) 85 | .OfType(); 86 | } 87 | 88 | public static FullNameParser Parse(string fullName) 89 | { 90 | var name = new FullNameParser(fullName); 91 | name.Parse(); 92 | return name; 93 | } 94 | 95 | /// 96 | /// Parses this instance. 97 | /// 98 | public void Parse() 99 | { 100 | DisplayName = FullName; 101 | if (string.IsNullOrWhiteSpace(FullName)) 102 | return; 103 | 104 | Preparse(); 105 | 106 | Results = PatternsMap 107 | .Select(pattern => pattern.Parse(FullName)) 108 | .Where(NotNull) 109 | .OrderByDescending(result => result?.Score ?? 0) 110 | .ToImmutableArray(); 111 | 112 | var selectedResult = Results.FirstOrDefault(); 113 | 114 | FirstName = selectedResult?.FirstName; 115 | MiddleName = selectedResult?.MiddleName; 116 | LastName = selectedResult?.LastName; 117 | Title = selectedResult?.Title; 118 | NickName = selectedResult?.NickName; 119 | Suffix = selectedResult?.Suffix; 120 | DisplayName = selectedResult?.DisplayName ?? FullName; 121 | } 122 | 123 | /// 124 | /// Removes the attn prefix if needed and remove all trailing and leading white spaces. 125 | /// 126 | protected void Preparse() 127 | { 128 | if (FullName.StartsWith("ATTN:", StringComparison.OrdinalIgnoreCase)) 129 | FullName = FullName.Substring(5).Trim(); 130 | 131 | FullName = FullName.Trim(); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Runtime.Loader; 8 | 9 | namespace BinaryFog.NameParser 10 | { 11 | internal static class Helpers 12 | { 13 | private static readonly Stopwatch Stopwatch = Stopwatch.StartNew(); 14 | 15 | private static long _lastCheckedLoadedAssemblies; 16 | private static ISet _knownAssemblies; 17 | 18 | /// 19 | /// A minimum freshness in milliseconds of the set. 20 | /// 21 | internal static int KnownAssembliesTimeout = 60000; 22 | 23 | /// 24 | /// A set of known loaded assemblies. 25 | /// Accurate to milliseconds. 26 | /// 27 | internal static ISet KnownAssemblies 28 | => CreateTimestamp() - _lastCheckedLoadedAssemblies < KnownAssembliesTimeout 29 | ? _knownAssemblies ?? GetLoadedAssemblies() 30 | : GetLoadedAssemblies(); 31 | 32 | /// 33 | /// A helper that returns the result of a , 34 | /// or in the event of an exception, . 35 | /// 36 | /// 37 | /// A given result type, the result of and the type of 38 | /// . 39 | /// 40 | /// A given function delegate that returns a or throws an exception. 41 | /// An alternative in the event that an exception is caught while executing . 42 | /// The result of or in the event of an exception, . 43 | internal static T TryOrDefault(Func fn, T @default = default) 44 | { 45 | try 46 | { 47 | return fn(); 48 | } 49 | catch 50 | { 51 | return @default; 52 | } 53 | } 54 | 55 | /// 56 | /// A shorthand helper for use with 57 | /// 58 | /// . 59 | /// 60 | /// A given class type, nullable. 61 | /// A possibly null or instance of . 62 | /// Returns true if is not null, otherwise false. 63 | internal static bool NotNull(T instance) where T : class 64 | { 65 | return instance != null; 66 | } 67 | 68 | /// 69 | /// Returns an arbitrary but incremental timestamp measured in milliseconds. 70 | /// Internally this uses the class. 71 | /// This provides no guarantee of starting time prior to the first call of this method. 72 | /// That means that time values returned by this method should only be compared to 73 | /// other time values returned by this method. 74 | /// 75 | /// An arbitrary timestamp in milliseconds. 76 | internal static long CreateTimestamp() 77 | { 78 | return Stopwatch.ElapsedMilliseconds; 79 | } 80 | 81 | /// 82 | /// Scans the current process for all loaded s 83 | /// and discovers them as an if they are one. 84 | /// This updates a cache of when called. 85 | /// 86 | /// A set of loaded assemblies. 87 | internal static ISet GetLoadedAssemblies() 88 | { 89 | _lastCheckedLoadedAssemblies = CreateTimestamp(); 90 | var procMods = Process.GetCurrentProcess().Modules.OfType(); 91 | var asmNames = procMods.Select(mod => TryOrDefault(() 92 | => AssemblyLoadContext.GetAssemblyName(mod.FileName))) 93 | .Where(NotNull); 94 | var asms = asmNames.Select(asmName => TryOrDefault(() 95 | => AssemblyLoadContext.Default.LoadFromAssemblyName(asmName))) 96 | .Where(NotNull); 97 | _knownAssemblies = asms.ToImmutableSortedSet(AssemblyComparer.Instance); 98 | return _knownAssemblies; 99 | } 100 | 101 | internal sealed class AssemblyComparer : IComparer 102 | { 103 | internal static readonly AssemblyComparer Instance = new AssemblyComparer(); 104 | 105 | // implementation varies between frameworks; 106 | // some eliminate need for ReferenceEquals compares, drops coverage by 1 line 107 | [ExcludeFromCodeCoverage] 108 | public int Compare(Assembly x, Assembly y) 109 | { 110 | if (x == null && y == null) return 0; 111 | if (x == null) return -1; 112 | if (y == null) return 1; 113 | if (ReferenceEquals(x, y)) return 0; 114 | var xHashCode = x.GetHashCode(); 115 | var yHashCode = y.GetHashCode(); 116 | return xHashCode == yHashCode 117 | ? string.Compare(x.FullName, y.FullName, StringComparison.Ordinal) 118 | : xHashCode < yHashCode 119 | ? -1 120 | : 1; 121 | } 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/IFullNamePattern.cs: -------------------------------------------------------------------------------- 1 | namespace BinaryFog.NameParser { 2 | /// 3 | /// Implement this interface if you wish for your name parser pattern 4 | /// to be automatically discovered and used by the . 5 | /// 6 | /// The implementing class must be public to be discovered automatically. 7 | /// 8 | /// Feel free to submit your patterns upstream to the repository or create a separate pattern library. 9 | /// 10 | public interface IFullNamePattern 11 | { 12 | 13 | /// 14 | /// Attempt to parse a name through the pattern. 15 | /// 16 | /// A raw name. 17 | /// A scored parsed result. 18 | ParsedFullName Parse(string rawName); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/NameComponentSets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Immutable; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.IO; 6 | 7 | namespace BinaryFog.NameParser 8 | { 9 | internal static class NameComponentSets { 10 | /// 11 | /// Reads lines from the stream as an enumeration of strings. 12 | /// 13 | /// The resource stream. 14 | /// Lines extracted as strings from the stream. 15 | public static IEnumerable ReadLines(Stream res) 16 | { 17 | using var reader = new StreamReader(res!); 18 | var line = reader.ReadLine(); 19 | while (!string.IsNullOrWhiteSpace(line)) { 20 | yield return line; 21 | line = reader.ReadLine(); 22 | } 23 | } 24 | 25 | 26 | [SuppressMessage("ReSharper", "InconsistentNaming")] private static readonly ImmutableHashSet _maleFirstNames = 27 | ReadLines(Resources.MaleFirstNames).ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); 28 | 29 | [SuppressMessage("ReSharper", "InconsistentNaming")] private static readonly ImmutableHashSet _femaleFirstNames = 30 | ReadLines(Resources.FemaleFirstNames).ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); 31 | 32 | public static readonly ISet MaleFirstNames = _maleFirstNames; 33 | public static readonly ISet FemaleFirstNames = _femaleFirstNames; 34 | 35 | 36 | public static readonly ISet FirstNames = 37 | _maleFirstNames?.Union(_femaleFirstNames); 38 | 39 | public static readonly ISet LastNames = 40 | ReadLines(Resources.LastNames).ToImmutableHashSet(StringComparer.OrdinalIgnoreCase); 41 | 42 | /// 43 | /// Apply adjustments to a score as a name is matched against the given dictionary. 44 | /// 45 | /// A given dictionary to match against. 46 | /// The score to adjust. 47 | /// The name to attempt to match. 48 | /// The value to adjust the score by if matched by the given dictionary. 49 | internal static void ModifyScore(ISet dictionary, ref int score, string name, int value) 50 | { 51 | if (dictionary.Contains(name)) score += value; 52 | } 53 | 54 | /// 55 | /// Apply adjustments to a score as a name is matched against first and last name dictionaries. 56 | /// 57 | /// The score to adjust. 58 | /// The name to attempt to match. 59 | /// The value to adjust the score by if matched by the first name dictionary. 60 | /// The value to adjust the score by if matched by the last name dictionary. 61 | internal static void ModifyScore(ref int score, string name, int matchedFirstValue, int matchedLastValue) { 62 | ModifyScore(FirstNames, ref score, name, matchedFirstValue); 63 | ModifyScore(FirstNames, ref score, name, matchedLastValue); 64 | } 65 | 66 | /// 67 | /// Apply a slight adjustment to a score if a name is matched against any name dictionary. 68 | /// 69 | /// The score to adjust. 70 | /// The name to attempt to match. 71 | /// The value to adjust the score by if matched. 72 | internal static void ModifyScoreExpectedName(ref int score, string name, int value = 10) 73 | => ModifyScore(ref score, name, value, value); 74 | 75 | /// 76 | /// Apply an adjustment to a score if a name is matched against the gender separated first name dictionaries. 77 | /// An additional adjustment is applied if the next name is also matched against the same dictionary. 78 | /// An opposite adjustments are applied if the names are matched in the last name dictionary. 79 | /// 80 | /// The score to adjust. 81 | /// The name to attempt to match as either male or female. 82 | /// The name to attempt to match as the same gender as the first. 83 | /// The value to adjust the score by if matched. 84 | internal static void ModifyScoreExpectedFirstNames(ref int score, string name1, string name2, int value = 10) { 85 | if (MaleFirstNames!.Contains(name1)) { 86 | if (!FemaleFirstNames!.Contains(name1)) 87 | score += value; 88 | if (MaleFirstNames.Contains(name2) && !FemaleFirstNames.Contains(name2)) { 89 | score += value; 90 | } 91 | } 92 | if (FemaleFirstNames!.Contains(name1)) { 93 | if (!MaleFirstNames.Contains(name1)) 94 | score += value; 95 | if (FemaleFirstNames.Contains(name2) && !MaleFirstNames.Contains(name2)) { 96 | score += value; 97 | } 98 | } 99 | if (LastNames!.Contains(name1)) score -= value; 100 | if (LastNames.Contains(name2)) score -= value; 101 | } 102 | 103 | /// 104 | /// Apply an adjustment to a score if a name is matched against the gender separated first name dictionaries. 105 | /// An additional adjustment is applied if the next names are also matched against the same dictionary. 106 | /// An opposite adjustments are applied if the names are matched in the last name dictionary. 107 | /// 108 | /// The score to adjust. 109 | /// The name to attempt to match as either male or female. 110 | /// The name to attempt to match as the same gender as the first. 111 | /// Another name to attempt to match as the same gender as the first. 112 | /// The value to adjust the score by if matched. 113 | internal static void ModifyScoreExpectedFirstNames(ref int score, string name1, string name2, string name3, int value = 10) { 114 | if (MaleFirstNames!.Contains(name1)) { 115 | if (!FemaleFirstNames!.Contains(name1)) 116 | score += value; 117 | if (MaleFirstNames.Contains(name2)) 118 | { 119 | if (!FemaleFirstNames.Contains(name2)) 120 | score += value; 121 | if (MaleFirstNames.Contains(name3) && !FemaleFirstNames.Contains(name3)) 122 | { 123 | score += value; 124 | } 125 | } 126 | } 127 | if (FemaleFirstNames!.Contains(name1)) { 128 | if (!MaleFirstNames.Contains(name1)) 129 | score += value; 130 | if (FemaleFirstNames.Contains(name2)) 131 | { 132 | if (!MaleFirstNames.Contains(name2)) 133 | score += value; 134 | if (FemaleFirstNames.Contains(name3) && !MaleFirstNames.Contains(name3)) { 135 | score += value; 136 | } 137 | } 138 | } 139 | if (LastNames!.Contains(name1)) score -= value; 140 | if (LastNames.Contains(name2)) score -= value; 141 | if (LastNames.Contains(name3)) score -= value; 142 | } 143 | 144 | /// 145 | /// Apply an adjustment to a score if a name is matched against the first name dictionary. 146 | /// An opposite adjustment is applied if the name is matched in the last name dictionary. 147 | /// 148 | /// The score to adjust. 149 | /// The name to attempt to match. 150 | /// The value to adjust the score by if matched. 151 | internal static void ModifyScoreExpectedFirstName(ref int score, string name, int value = 25) { 152 | ModifyScore(FirstNames, ref score, name, value); 153 | ModifyScore(LastNames, ref score, name, -value); 154 | } 155 | 156 | /// 157 | /// Apply an adjustment to a score if a name is matched against the last name dictionary. 158 | /// An opposite adjustment is applied if the name is matched in the first name dictionary. 159 | /// 160 | /// The score to adjust. 161 | /// The name to attempt to match. 162 | /// The value to adjust the score by if matched. 163 | internal static void ModifyScoreExpectedLastName(ref int score, string name, int value = 25) { 164 | ModifyScore(LastNames, ref score, name, value); 165 | ModifyScore(FirstNames, ref score, name, -value); 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/ParsedFullName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace BinaryFog.NameParser 5 | { 6 | #if DEBUG_FULL_NAME_PATTERN_RESULTS 7 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")] 8 | #endif 9 | public sealed class ParsedFullName 10 | { 11 | #if DEBUG_FULL_NAME_PATTERN_RESULTS 12 | /* 13 | * This is used for determining indisputably which IFullNamePattern 14 | * implementation constructed this ParsedFullName instance. 15 | * You might have to adjust this for your specific platform. 16 | */ 17 | [ExcludeFromCodeCoverage] 18 | private static Type GetOuterStackFrameType(int frameOffset = 0) { 19 | var st = (StackTrace) typeof(StackTrace).GetConstructor(Type.EmptyTypes).Invoke(null); 20 | var frames = st.GetFrames(); 21 | var thisType = typeof(ParsedFullName); 22 | var frameIndex = 0; 23 | // find this call 24 | while (frames[frameIndex].GetMethod().DeclaringType != thisType) 25 | ++frameIndex; 26 | // find the outermost call to the class 27 | while (frames[frameIndex].GetMethod().DeclaringType == thisType) 28 | ++frameIndex; 29 | return frames[frameIndex+frameOffset].GetMethod().DeclaringType; 30 | } 31 | 32 | [ExcludeFromCodeCoverage] 33 | private Type Pattern { get; } = GetOuterStackFrameType(); 34 | 35 | [ExcludeFromCodeCoverage] 36 | private string DebuggerDisplay => $"{Score:G4} {Pattern.Name}: {DisplayName}"; 37 | #endif 38 | public const int MaxScore = int.MaxValue; 39 | 40 | public string FirstName { get; set; } 41 | public string MiddleName { get; set; } 42 | public string LastName { get; set; } 43 | public string Title { get; set; } 44 | public string NickName { get; set; } 45 | public string Suffix { get; set; } 46 | 47 | /// 48 | /// This property is intended to display all names as would appear for presentation purposes. 49 | /// This excludes titles and suffixes. 50 | /// 51 | public string DisplayName { get; set; } 52 | 53 | public int Score { get; set; } 54 | } 55 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/AfricanFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | 5 | namespace BinaryFog.NameParser.Patterns 6 | { 7 | [UsedImplicitly] 8 | public class AfricanFirstLastPattern : IFullNamePattern 9 | { 10 | private static readonly string Pattern = $@"^{AfricanFirst}{Space}{Last}$"; 11 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 12 | 13 | public ParsedFullName Parse(string rawName) 14 | { 15 | if (rawName == null) return null; 16 | var match = Rx!.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | 20 | var firstName = match.Groups["first"]?.Value; 21 | var lastPart = match.Groups["last"]?.Value; 22 | var lastName = $"{lastPart}"; 23 | 24 | var pn = new ParsedFullName 25 | { 26 | FirstName = firstName, 27 | LastName = lastName, 28 | DisplayName = $"{firstName} {lastName}", 29 | Score = 1200 30 | }; 31 | return pn; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/CompanyPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | 5 | namespace BinaryFog.NameParser.Patterns { 6 | [UsedImplicitly] 7 | public class CompanyPattern : IFullNamePattern 8 | { 9 | private static readonly string Pattern = $@"{Space}(?({CompanySuffixes})\W?)$"; 10 | private static readonly Regex Rx = new Regex(Pattern!, CommonPatternRegexOptions); 11 | 12 | 13 | public ParsedFullName Parse(string rawName) 14 | { 15 | if (rawName == null) return null; 16 | var match = Rx!.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | 20 | var pn = new ParsedFullName { 21 | DisplayName = rawName, 22 | Score = ParsedFullName.MaxScore 23 | }; 24 | 25 | return pn; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstHyphenatedLastNickPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.NameComponentSets; 4 | using static BinaryFog.NameParser.RegexNameComponents; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstHyphenatedLastNickPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{LastHyphenated}{OptionalSpace}{Nick}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"]?.Value; 21 | var lastPart1 = match.Groups["last1"]?.Value; 22 | var lastPart2 = match.Groups["last2"]?.Value; 23 | var lastName = $"{lastPart1}-{lastPart2}"; 24 | var nickName = match.Groups["nick"]?.Value; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 30 | ModifyScoreExpectedName(ref scoreMod, nickName); 31 | 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | LastName = lastName, 36 | NickName = nickName, 37 | DisplayName = $"{firstName} {lastName}", 38 | Score = 0 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{LastHyphenated}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"]?.Value; 21 | var lastPart1 = match.Groups["last1"]?.Value; 22 | var lastPart2 = match.Groups["last2"]?.Value; 23 | var lastName = $"{lastPart1}-{lastPart2}"; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | FirstName = firstName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {lastPart1}-{lastPart2}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using static BinaryFog.NameParser.RegexNameComponents; 3 | using static BinaryFog.NameParser.NameComponentSets; 4 | 5 | namespace BinaryFog.NameParser.Patterns 6 | { 7 | public class FirstInitialHyphenatedLastPattern : IFullNamePattern 8 | { 9 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{LastHyphenated}$"; 10 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 11 | 12 | public ParsedFullName Parse(string rawName) 13 | { 14 | if (rawName == null) return null; 15 | var match = Rx!.Match(rawName); 16 | if (!match.Success) return null; 17 | 18 | var firstName = match.Groups["first"]?.Value; 19 | var middleName = $"{match.Groups["initial"]}."; 20 | var lastPart1 = match.Groups["last1"]?.Value; 21 | var lastPart2 = match.Groups["last2"]?.Value; 22 | var lastName = $"{lastPart1}-{lastPart2}"; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | MiddleName = middleName, 32 | LastName = lastName, 33 | DisplayName = $"{firstName} {middleName} {lastName}", 34 | Score = 100 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialHyphenatedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialHyphenatedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{LastHyphenated}{Space}{Suffix}$"; 12 | 13 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 14 | 15 | public ParsedFullName Parse(string rawName) 16 | { 17 | if (rawName == null) return null; 18 | var match = Rx!.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"]?.Value; 21 | var middleName = $"{match.Groups["initial"]}."; 22 | var lastPart1 = match.Groups["last1"]?.Value; 23 | var lastPart2 = match.Groups["last2"]?.Value; 24 | var lastName = $"{lastPart1}-{lastPart2}"; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | MiddleName = middleName, 35 | LastName = lastName, 36 | Suffix = match.Groups["suffix"]?.Value, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Score = 100 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialLastCommaSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialLastCommaSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{Last}{CommaSpace}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var middleName = $"{match.Groups["initial"]}."; 21 | var lastName = match.Groups["last"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 26 | 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | MiddleName = middleName, 31 | LastName = lastName, 32 | Suffix = match.Groups["suffix"].Value, 33 | DisplayName = $"{firstName} {middleName} {lastName}", 34 | Score = 100 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var middleName = $"{match.Groups["initial"]}."; 21 | var lastName = match.Groups["last"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 26 | 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | MiddleName = middleName, 31 | LastName = lastName, 32 | DisplayName = $"{firstName} {middleName} {lastName}", 33 | Score = 100 + scoreMod 34 | }; 35 | return pn; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{Last}{Space}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var middleName = $"{match.Groups["initial"]}."; 21 | var lastName = match.Groups["last"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 26 | 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | MiddleName = middleName, 31 | LastName = lastName, 32 | Suffix = match.Groups["suffix"].Value, 33 | DisplayName = $"{firstName} {middleName} {lastName}", 34 | Score = 100 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialPrefixedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialPrefixedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Initial}{Space}{Prefix}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var middleName = $"{match.Groups["initial"]}."; 21 | var prefix = match.Groups["prefix"].Value; 22 | var lastPart = match.Groups["last"].Value; 23 | var lastName = $"{prefix} {lastPart}"; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstInitialPrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstInitialPrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{Space}{Initial}{Space}{Prefix}{Space}{Last}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | var firstName = match.Groups["first"].Value; 22 | var middleName = $"{match.Groups["initial"]}."; 23 | var prefix = match.Groups["prefix"].Value; 24 | var lastPart = match.Groups["last"].Value; 25 | var lastName = $"{prefix} {lastPart}"; 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | MiddleName = middleName, 35 | LastName = lastName, 36 | Suffix = match.Groups["suffix"].Value, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Score = 100 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstIrishLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstIrishLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}(?O'|Mc|Mac){Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | 21 | var firstName = match.Groups["first"].Value; 22 | var irishPrefix = match.Groups["irishPrefix"].Value; 23 | var lastPart = match.Groups["last"].Value; 24 | var lastName = $"{irishPrefix}{lastPart}"; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | FirstName = firstName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {lastName}", 35 | Score = 300 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstLastNickPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.NameComponentSets; 4 | using static BinaryFog.NameParser.RegexNameComponents; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstLastNickPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Last}{OptionalSpace}{Nick}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | ModifyScoreExpectedName(ref scoreMod, nickName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | LastName = lastName, 33 | NickName = nickName, 34 | DisplayName = $"{firstName} {lastName}", 35 | Score = 0 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 26 | 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | LastName = lastName, 31 | DisplayName = $"{firstName} {lastName}", 32 | Score = 10 + scoreMod 33 | }; 34 | return pn; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Last}{OptionalCommaSpace}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 26 | 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | LastName = lastName, 31 | DisplayName = $"{firstName} {lastName}", 32 | Suffix = match.Groups["suffix"].Value, 33 | Score = 200 + scoreMod 34 | }; 35 | return pn; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstLastSuffixSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstLastSuffixSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Last}{OptionalCommaSpace}{Suffix1}{OptionalCommaSpace}{Suffix2}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var suffix = $@"{match.Groups["suffix1"].Value} {match.Groups["suffix2"].Value}"; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | LastName = lastName, 32 | DisplayName = $"{firstName} {lastName}", 33 | Suffix = suffix, 34 | Score = 200 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddleHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddleHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Middle}{Space}{LastHyphenated}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = match.Groups["middle"].Value; 22 | 23 | var lastPart1 = match.Groups["last1"].Value; 24 | var lastPart2 = match.Groups["last2"].Value; 25 | 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 31 | 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = $"{lastPart1}-{lastPart2}", 37 | DisplayName = $"{firstName} {middleName} {lastPart1}-{lastPart2}", 38 | Score = 10 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddleHyphenatedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddleHyphenatedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Middle}{Space}{LastHyphenated}{Space}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = match.Groups["middle"].Value; 22 | 23 | var lastPart1 = match.Groups["last1"].Value; 24 | var lastPart2 = match.Groups["last2"].Value; 25 | 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 31 | 32 | var lastName = $"{lastPart1}-{lastPart2}"; 33 | var pn = new ParsedFullName 34 | { 35 | FirstName = firstName, 36 | MiddleName = middleName, 37 | LastName = lastName, 38 | Suffix = match.Groups["suffix"].Value, 39 | DisplayName = $"{firstName} {middleName} {lastName}", 40 | Score = 10 + scoreMod 41 | }; 42 | return pn; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddleLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddleLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Middle}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = match.Groups["middle"].Value; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | MiddleName = middleName, 32 | LastName = lastName, 33 | DisplayName = $"{firstName} {middleName} {lastName}", 34 | Score = 50 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddleLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddleLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Middle}{Space}{Last}{Space}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = match.Groups["middle"].Value; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | MiddleName = middleName, 32 | LastName = lastName, 33 | Suffix = match.Groups["suffix"].Value, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddlePrefixedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddlePrefixedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Middle}{Space}{Prefix}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var prefix = match.Groups["prefix"].Value; 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = match.Groups["middle"].Value; 22 | var lastPart = match.Groups["last"].Value; 23 | var lastName = $"{prefix} {lastPart}"; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | 34 | LastName = lastName, 35 | DisplayName = $"{firstName} {middleName} {lastName}", 36 | Score = 250 + scoreMod 37 | }; 38 | return pn; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddlePrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddlePrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string 12 | Pattern = $@"^{First}{Space}{Middle}{Space}{Prefix}{Space}{Last}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | 17 | public ParsedFullName Parse(string rawName) 18 | { 19 | if (rawName == null) return null; 20 | var match = Rx!.Match(rawName); 21 | if (!match.Success) return null; 22 | var prefix = match.Groups["prefix"].Value; 23 | var firstName = match.Groups["first"].Value; 24 | var middleName = match.Groups["middle"].Value; 25 | var lastPart = match.Groups["last"].Value; 26 | var lastName = $"{prefix} {lastPart}"; 27 | 28 | var scoreMod = 0; 29 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 31 | 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = lastName, 37 | Suffix = match.Groups["suffix"].Value, 38 | DisplayName = $"{firstName} {middleName} {lastName}", 39 | Score = 250 + scoreMod 40 | }; 41 | return pn; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstMiddleTwoLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstMiddleTwoLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{Space}{Middle}{Space}(?{Name}){Space}(?{Name})$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | 22 | var firstName = match.Groups["first"].Value; 23 | var middleName = match.Groups["middle"].Value; 24 | var lastPart1 = match.Groups["last1"].Value; 25 | var lastPart2 = match.Groups["last2"].Value; 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 31 | 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = $"{lastPart1} {lastPart2}", 37 | DisplayName = $"{firstName} {middleName} {lastPart1} {lastPart2}", 38 | Score = 50 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNameJobTitlePattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNameJobTitlePattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{JobTitle}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var jobTitle = match.Groups["jobTitle"].Value; 20 | var firstName = match.Groups["first"].Value; 21 | 22 | var scoreMod = 0; 23 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 24 | 25 | var pn = new ParsedFullName 26 | { 27 | FirstName = firstName, 28 | 29 | DisplayName = $"{firstName} {jobTitle}", 30 | Score = 200 + scoreMod 31 | }; 32 | return pn; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNickHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNickHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{OptionalSpace}{Nick}{OptionalSpace}{LastHyphenated}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | 22 | var firstName = match.Groups["first"].Value; 23 | var nickName = match.Groups["nick"].Value; 24 | var lastPart1 = match.Groups["last1"].Value; 25 | var lastPart2 = match.Groups["last2"].Value; 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 29 | ModifyScoreExpectedName(ref scoreMod, nickName); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 31 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 32 | 33 | 34 | var pn = new ParsedFullName 35 | { 36 | FirstName = firstName, 37 | NickName = nickName, 38 | LastName = $"{lastPart1}-{lastPart2}", 39 | DisplayName = $"{firstName} {lastPart1}-{lastPart2}", 40 | Score = 75 + scoreMod 41 | }; 42 | return pn; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNickInitialLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNickInitialLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{OptionalSpace}{Nick}{OptionalSpace}{Initial}{Space}{Last}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | var firstName = match.Groups["first"].Value; 22 | var middleName = match.Groups["initial"].Value; 23 | var lastName = match.Groups["last"].Value; 24 | var nickName = match.Groups["nick"].Value; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedName(ref scoreMod, nickName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | MiddleName = $"{middleName}.", 35 | LastName = lastName, 36 | NickName = nickName, 37 | DisplayName = $"{firstName} {middleName}. {lastName}", 38 | Score = 200 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNickLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNickLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{OptionalSpace}{Nick}{OptionalSpace}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var lastName = match.Groups["last"].Value; 21 | var nickName = match.Groups["nick"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedName(ref scoreMod, nickName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | LastName = lastName, 32 | NickName = nickName, 33 | DisplayName = $"{firstName} {lastName}", 34 | Score = 100 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNickMiddleHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNickMiddleHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{OptionalSpace}{Nick}{OptionalSpace}{Middle}{Space}{LastHyphenated}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | var firstName = match.Groups["first"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | var middleName = match.Groups["middle"].Value; 24 | var lastPart1 = match.Groups["last1"].Value; 25 | var lastPart2 = match.Groups["last2"].Value; 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 29 | ModifyScoreExpectedName(ref scoreMod, nickName); 30 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 31 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 32 | 33 | var pn = new ParsedFullName 34 | { 35 | FirstName = firstName, 36 | NickName = nickName, 37 | MiddleName = middleName, 38 | LastName = $"{lastPart1}-{lastPart2}", 39 | DisplayName = $"{firstName} {middleName} {lastPart1}-{lastPart2}", 40 | Score = 175 + scoreMod 41 | }; 42 | return pn; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstNickMiddleLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstNickMiddleLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{First}{OptionalSpace}{Nick}{OptionalSpace}{Middle}{Space}{Last}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | if (rawName == null) return null; 19 | var match = Rx!.Match(rawName); 20 | if (!match.Success) return null; 21 | var firstName = match.Groups["first"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | var middleName = match.Groups["middle"].Value; 24 | var lastName = match.Groups["last"].Value; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName); 28 | ModifyScoreExpectedName(ref scoreMod, nickName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | NickName = nickName, 35 | MiddleName = middleName, 36 | LastName = lastName, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Score = 125 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstPrefixedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstPrefixedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Prefix}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var prefix = match.Groups["prefix"].Value; 20 | var firstName = match.Groups["first"].Value; 21 | var lastPart = match.Groups["last"].Value; 22 | 23 | var lastName = $"{prefix} {lastPart}"; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 28 | var pn = new ParsedFullName 29 | { 30 | FirstName = firstName, 31 | LastName = lastName, 32 | DisplayName = $"{firstName} {lastName}", 33 | Score = 275 + scoreMod 34 | }; 35 | return pn; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstPrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.NameComponentSets; 4 | using static BinaryFog.NameParser.RegexNameComponents; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstPrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{Prefix}{Space}{Last}{Space}{Suffix}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var prefix = match.Groups["prefix"].Value; 20 | var firstName = match.Groups["first"].Value; 21 | var lastPart = match.Groups["last"].Value; 22 | var lastName = $"{prefix} {lastPart}"; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 27 | var pn = new ParsedFullName 28 | { 29 | FirstName = firstName, 30 | LastName = lastName, 31 | Suffix = match.Groups["suffix"].Value, 32 | DisplayName = $"{firstName} {lastName}", 33 | Score = 275 + scoreMod 34 | }; 35 | return pn; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstTwoHyphenatedMiddleLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstTwoHyphenatedMiddleLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{TwoHyphenOptionallySpacedMiddle}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | var firstName = match.Groups["first"].Value; 20 | var middleName1 = match.Groups["middle1"].Value; 21 | var middleName2 = match.Groups["middle2"].Value; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName1, middleName2); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var middleName = IsHyphenated(rawName) ? $"{middleName1}-{middleName2}" : $"{middleName1} {middleName2}"; 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 50 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | 40 | private bool IsHyphenated( string rawName) 41 | { 42 | string Pattern = $@"{Hyphen}"; 43 | Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 44 | 45 | var match = Rx.Match(rawName); 46 | return match.Success; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstTwoLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstTwoLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}(?{Name}){Space}(?{Name})$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | if (rawName == null) return null; 17 | var match = Rx!.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | 21 | var lastPart1 = match.Groups["last1"].Value; 22 | var lastPart2 = match.Groups["last2"].Value; 23 | 24 | var lastName = $"{lastPart1} {lastPart2}"; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | LastName = lastName, 35 | DisplayName = $"{firstName} {lastName}", 36 | Score = 25 + scoreMod 37 | }; 38 | return pn; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstTwoMiddleHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstTwoMiddleHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{TwoMiddle}{Space}{LastHyphenated}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | var firstName = match.Groups["first"].Value; 20 | var middleName1 = match.Groups["middle1"].Value; 21 | var middleName2 = match.Groups["middle2"].Value; 22 | var lastPart1 = match.Groups["last1"].Value; 23 | var lastPart2 = match.Groups["last2"].Value; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName1, middleName2); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 29 | 30 | var lastName = $"{lastPart1}-{lastPart2}"; 31 | var middleName = $"{middleName1} {middleName2}"; 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = lastName, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Score = 75 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/FirstTwoMiddleLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class FirstTwoMiddleLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}{Space}{TwoMiddle}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | var firstName = match.Groups["first"].Value; 20 | var middleName1 = match.Groups["middle1"].Value; 21 | var middleName2 = match.Groups["middle2"].Value; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName1, middleName2); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var middleName = $"{middleName1} {middleName2}"; 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 50 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/HyphenatedFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class HyphenatedFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^(?\w+){HyphenOptionallySpaced}(?{Name}){Space}(?{Name})$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | 21 | var firstPart1 = match.Groups["first1"].Value; 22 | var firstPart2 = match.Groups["first2"].Value; 23 | var firstName = $"{match.Groups["first1"].Value}-{match.Groups["first2"].Value}"; 24 | var lastName = match.Groups["last"].Value; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstNames(ref scoreMod, firstPart1, firstPart2); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 29 | 30 | 31 | var pn = new ParsedFullName 32 | { 33 | FirstName = firstName, 34 | LastName = lastName, 35 | DisplayName = $"{firstName} {lastName}", 36 | Score = 100 + scoreMod 37 | }; 38 | return pn; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/LastNameCommaFirstNameInitialPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class LastNameCommaFirstNameInitialPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Last}{CommaSpace}{First}{Space}{Initial}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var firstName = match.Groups["first"].Value; 19 | var lastName = match.Groups["last"].Value; 20 | var middleName = match.Groups["initial"].Value; 21 | 22 | var scoreMod = 0; 23 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 24 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 25 | 26 | var pn = new ParsedFullName 27 | { 28 | FirstName = firstName, 29 | LastName = lastName, 30 | MiddleName = middleName, 31 | DisplayName = $"{firstName} {middleName}. {lastName}", 32 | Score = 100 + scoreMod 33 | }; 34 | return pn; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/LastNameCommaFirstNameMiddleNameSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class LastNameCommaFirstNameMiddleNameSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Last}{CommaSpace}{First}{Space}{Middle}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var middleName = match.Groups["middle"].Value; 23 | var suffix = match.Groups["suffix"].Value; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedName(ref scoreMod, middleName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | FirstName = firstName, 33 | LastName = lastName, 34 | MiddleName = middleName, 35 | Suffix = suffix, 36 | 37 | DisplayName = $"{firstName} {lastName}", 38 | Score = 100 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/LastNameCommaFirstNameNickNameInitialPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class LastNameCommaFirstNameNickNameInitialPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Last}{CommaSpace}{First}{OptionalSpace}{Nick}{OptionalSpace}{Initial}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedName(ref scoreMod, nickName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | LastName = lastName, 33 | NickName = nickName, 34 | 35 | DisplayName = $"{firstName} {lastName}", 36 | Score = 100 + scoreMod 37 | }; 38 | return pn; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/LastNameCommaFirstNamePattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class LastNameCommaFirstNamePattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Last}{CommaSpace}{First}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var firstName = match.Groups["first"].Value; 19 | var lastName = match.Groups["last"].Value; 20 | 21 | var scoreMod = 0; 22 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 23 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 24 | 25 | var pn = new ParsedFullName 26 | { 27 | FirstName = firstName, 28 | LastName = lastName, 29 | DisplayName = $"{firstName} {lastName}", 30 | Score = 100 + scoreMod 31 | }; 32 | return pn; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/SingleHyphenatedLastNameCommaFirstNameMiddleName.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class SingleHyphenatedLastNameCommaFirstNameMiddleName : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{LastHyphenated}{CommaSpace}{First}{Space}{Middle}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var middleName = match.Groups["middle"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedName(ref scoreMod, middleName); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | LastName = lastName, 33 | MiddleName = middleName, 34 | 35 | DisplayName = $"{firstName} {lastName}", 36 | Score = 100 + scoreMod 37 | }; 38 | return pn; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/SingleHyphenatedLastNameCommaFirstNameMiddleNameSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class SingleHyphenatedLastNameCommaFirstNameMiddleNameSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{LastHyphenated}{CommaSpace}{First}{Space}{Middle}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var middleName = match.Groups["middle"].Value; 23 | var suffix = match.Groups["suffix"].Value; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedName(ref scoreMod, middleName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | FirstName = firstName, 33 | LastName = lastName, 34 | MiddleName = middleName, 35 | Suffix = suffix, 36 | 37 | DisplayName = $"{firstName} {lastName}", 38 | Score = 100 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/SingleHyphenatedNameOnlyPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class SingleHyphenatedNameOnlyPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{LastHyphenated}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | 15 | public ParsedFullName Parse(string rawName) 16 | { 17 | var match = Rx.Match(rawName); 18 | if (!match.Success) return null; 19 | 20 | var lastPart1 = match.Groups["last1"].Value; 21 | var lastPart2 = match.Groups["last2"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 26 | 27 | var lastName = $"{lastPart1}-{lastPart2}"; 28 | 29 | var pn = new ParsedFullName 30 | { 31 | LastName = lastName, 32 | DisplayName = lastName, 33 | Score = 50 + scoreMod 34 | }; 35 | 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/SingleNameOnlyPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class SingleNameOnlyPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{First}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | 15 | public ParsedFullName Parse(string rawName) 16 | { 17 | var match = Rx.Match(rawName); 18 | if (!match.Success) return null; 19 | var pn = new ParsedFullName 20 | { 21 | DisplayName = rawName, 22 | Score = 50 23 | }; 24 | 25 | var matchedName = match.Groups["first"].Value; 26 | 27 | if (LastNames.Contains(matchedName)) 28 | pn.LastName = matchedName; 29 | else 30 | pn.FirstName = matchedName; 31 | 32 | return pn; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstHyphenatedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstHyphenatedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Title}{Space}{First}{Space}{LastHyphenated}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | 19 | var firstName = match.Groups["first"].Value; 20 | var lastPart1 = match.Groups["last1"].Value; 21 | var lastPart2 = match.Groups["last2"].Value; 22 | 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | Title = match.Groups["title"].Value, 31 | FirstName = firstName, 32 | LastName = $"{lastPart1}-{lastPart2}", 33 | DisplayName = $"{firstName} {lastPart1}-{lastPart2}", 34 | Score = 200 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstInitialLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstInitialLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Title}{Space}{First}{Space}{Initial}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | 15 | public ParsedFullName Parse(string rawName) 16 | { 17 | //Title should be Mr or Mr. or Ms or Ms. or Mrs or Mrs. 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var middleName = $"{match.Groups["initial"].Value}."; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | Title = match.Groups["title"].Value, 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstInitialLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstInitialLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}{Initial}{Space}{Last}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | 21 | var title = match.Groups["title"].Value; 22 | var firstName = match.Groups["first"].Value; 23 | var middleName = $"{match.Groups["initial"]}."; 24 | var lastName = match.Groups["last"].Value; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | Title = title, 33 | FirstName = firstName, 34 | MiddleName = middleName, 35 | LastName = lastName, 36 | Suffix = match.Groups["suffix"].Value, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Score = 100 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstInitialPrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstInitialPrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}{Initial}{Space}{Prefix}{Space}{Last}{Space}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var title = match.Groups["title"].Value; 21 | var firstName = match.Groups["first"].Value; 22 | var middleName = $"{match.Groups["initial"]}."; 23 | var prefix = match.Groups["prefix"].Value; 24 | var lastPart = match.Groups["last"].Value; 25 | var lastName = $"{prefix} {lastPart}"; 26 | 27 | var scoreMod = 0; 28 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 29 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 30 | 31 | var pn = new ParsedFullName 32 | { 33 | Title = title, 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = lastName, 37 | Suffix = match.Groups["suffix"].Value, 38 | DisplayName = $"{firstName} {middleName} {lastName}", 39 | Score = 100 40 | }; 41 | return pn; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstIrishLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstIrishLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}(?O'|Mc|Mac){Last}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | //Title should be Mr or Mr. or Ms or Ms. or Mrs or Mrs. 19 | var match = Rx.Match(rawName); 20 | if (!match.Success) return null; 21 | var firstName = match.Groups["first"].Value; 22 | var irishPrefix = match.Groups["irishPrefix"].Value; 23 | var lastPart = match.Groups["last"].Value; 24 | var lastName = $"{irishPrefix}{lastPart}"; 25 | 26 | var scoreMod = 0; 27 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | Title = match.Groups["title"].Value, 33 | FirstName = firstName, 34 | LastName = lastName, 35 | DisplayName = $"{firstName} {lastName}", 36 | Score = 300 + scoreMod 37 | }; 38 | 39 | return pn; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Title}{Space}{First}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | //Title should be Mr or Mr. or Ms or Ms. or Mrs or Mrs. 17 | var match = Rx.Match(rawName); 18 | if (!match.Success) return null; 19 | var firstName = match.Groups["first"].Value; 20 | var lastName = match.Groups["last"].Value; 21 | var scoreMod = 0; 22 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 23 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 24 | var pn = new ParsedFullName 25 | { 26 | Title = match.Groups["title"].Value, 27 | FirstName = firstName, 28 | LastName = lastName, 29 | DisplayName = $"{firstName} {lastName}", 30 | Score = 100 + scoreMod 31 | }; 32 | 33 | return pn; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}{Last}{OptionalCommaSpace}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | //Title should be Mr or Mr. or Ms or Ms. or Mrs or Mrs. 19 | //Suffix should be I or II or III or Jr. or Jr or Sr. or Sr or ESQ or ESQ. or ESQ" 20 | var match = Rx.Match(rawName); 21 | if (!match.Success) return null; 22 | var firstName = match.Groups["first"].Value; 23 | var lastName = match.Groups["last"].Value; 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | 28 | var pn = new ParsedFullName 29 | { 30 | Title = match.Groups["title"].Value, 31 | FirstName = firstName, 32 | LastName = lastName, 33 | DisplayName = $"{firstName} {lastName}", 34 | Suffix = match.Groups["suffix"].Value, 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstMiddlePrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstMiddlePrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}{Middle}{Space}{Prefix}{Space}{Last}{OptionalCommaSpace}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var prefix = match.Groups["prefix"].Value; 21 | var firstName = match.Groups["first"].Value; 22 | var middleName = match.Groups["middle"].Value; 23 | var lastName = match.Groups["last"].Value; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 27 | ModifyScoreExpectedFirstName(ref scoreMod, middleName, 10); 28 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 29 | 30 | var pn = new ParsedFullName 31 | { 32 | Title = match.Groups["title"].Value, 33 | FirstName = firstName, 34 | MiddleName = middleName, 35 | LastName = prefix + " " + lastName, 36 | Suffix = match.Groups["suffix"].Value, 37 | DisplayName = $"{firstName} {middleName} {prefix} {lastName}", 38 | Score = 300 + scoreMod 39 | }; 40 | return pn; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstNameJobTitlePattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstNameJobTitlePattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Title}{Space}{First}{Space}{JobTitle}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | 15 | public ParsedFullName Parse(string rawName) 16 | { 17 | var match = Rx.Match(rawName); 18 | if (!match.Success) return null; 19 | var jobTitle = match.Groups["jobTitle"].Value; 20 | var firstName = match.Groups["first"].Value; 21 | 22 | var scoreMod = 0; 23 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 24 | 25 | var pn = new ParsedFullName 26 | { 27 | Title = match.Groups["title"].Value, 28 | FirstName = firstName, 29 | 30 | DisplayName = $"{firstName} {jobTitle}", 31 | Score = 200 + scoreMod 32 | }; 33 | return pn; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstNickLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstNickLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{OptionalSpace}{Nick}{OptionalSpace}{Last}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedName(ref scoreMod, nickName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | var pn = new ParsedFullName 28 | { 29 | Title = match.Groups["title"].Value, 30 | FirstName = firstName, 31 | LastName = lastName, 32 | NickName = nickName, 33 | DisplayName = $"{firstName} {lastName}", 34 | Score = 100 + scoreMod 35 | }; 36 | return pn; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstNickLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstNickLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{OptionalSpace}{Nick}{OptionalSpace}{Last}{OptionalCommaSpace}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastName = match.Groups["last"].Value; 22 | var nickName = match.Groups["nick"].Value; 23 | var scoreMod = 0; 24 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 25 | ModifyScoreExpectedName(ref scoreMod, nickName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 27 | var pn = new ParsedFullName 28 | { 29 | Title = match.Groups["title"].Value, 30 | FirstName = firstName, 31 | LastName = lastName, 32 | NickName = nickName, 33 | DisplayName = $"{firstName} {lastName}", 34 | Suffix = match.Groups["suffix"].Value, 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstPrefixedLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstPrefixedLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{Title}{Space}{First}{Space}{Prefix}{Space}{Last}$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var prefix = match.Groups["prefix"].Value; 19 | var firstName = match.Groups["first"].Value; 20 | var lastPart = match.Groups["last"].Value; 21 | var lastName = $"{prefix} {lastPart}"; 22 | var scoreMod = 0; 23 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 24 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 25 | var pn = new ParsedFullName 26 | { 27 | Title = match.Groups["title"].Value, 28 | FirstName = firstName, 29 | 30 | LastName = lastName, 31 | DisplayName = $"{firstName} {lastName}", 32 | Score = 275 + scoreMod 33 | }; 34 | return pn; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstTwoLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstTwoLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}(?{Name}){Space}(?{Name})$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var firstName = match.Groups["first"].Value; 21 | var lastPart1 = match.Groups["last1"].Value; 22 | var lastPart2 = match.Groups["last2"].Value; 23 | 24 | var scoreMod = 0; 25 | ModifyScoreExpectedFirstName(ref scoreMod, firstName); 26 | ModifyScoreExpectedLastName(ref scoreMod, lastPart1); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastPart2); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | Title = match.Groups["title"].Value, 32 | FirstName = firstName, 33 | LastName = $"{lastPart1} {lastPart2}", 34 | DisplayName = $"{firstName} {lastPart1} {lastPart2}", 35 | Score = 50 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleFirstTwoMiddlePrefixedLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleFirstTwoMiddlePrefixedLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}{First}{Space}(?{Name}){Space}(?{Name}){Space}{Prefix}{Space}{Last}{OptionalCommaSpace}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var prefix = match.Groups["prefix"].Value; 21 | var firstName = match.Groups["first"].Value; 22 | var middleName1 = match.Groups["middle1"].Value; 23 | var middleName2 = match.Groups["middle2"].Value; 24 | var lastPart = match.Groups["last"].Value; 25 | 26 | var middleName = $"{middleName1} {middleName2}"; 27 | var lastName = $"{prefix} {lastPart}"; 28 | 29 | var scoreMod = 0; 30 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName, middleName1, middleName2); 31 | ModifyScoreExpectedLastName(ref scoreMod, lastPart); 32 | 33 | var pn = new ParsedFullName 34 | { 35 | Title = match.Groups["title"].Value, 36 | FirstName = firstName, 37 | MiddleName = middleName, 38 | LastName = lastName, 39 | Suffix = match.Groups["suffix"].Value, 40 | DisplayName = $"{firstName} {middleName} {lastName}", 41 | Score = 275 + scoreMod 42 | }; 43 | return pn; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TitleHyphenatedFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TitleHyphenatedFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{Title}{Space}(?{Name})-(?{Name}){Space}(?{Name})$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | 21 | var firstName1 = match.Groups["first1"].Value; 22 | var firstName2 = match.Groups["first2"].Value; 23 | var lastName = match.Groups["last"].Value; 24 | 25 | var scoreMod = 0; 26 | ModifyScoreExpectedFirstNames(ref scoreMod, firstName1, firstName2); 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | Title = match.Groups["title"].Value, 32 | FirstName = $"{firstName1}-{firstName2}", 33 | LastName = lastName, 34 | DisplayName = $"{firstName1}-{firstName2} {lastName}", 35 | Score = 200 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TwoInitialsFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TwoInitialsFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{TwoInitial}{Space}(?\w+)$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var initial1 = match.Groups["initial1"].Value; 19 | var initial2 = match.Groups["initial2"].Value; 20 | var firstName = $"{initial1}."; 21 | var middleName = $"{initial2}."; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | 25 | var scoreMod = 0; 26 | 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TwoInitialsFirstLastSuffixPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TwoInitialsFirstLastSuffixPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = 12 | $@"^{TwoInitial}{Space}(?\w+){OptionalCommaSpace}{Suffix}$"; 13 | 14 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 15 | 16 | public ParsedFullName Parse(string rawName) 17 | { 18 | var match = Rx.Match(rawName); 19 | if (!match.Success) return null; 20 | var initial1 = match.Groups["initial1"].Value; 21 | var initial2 = match.Groups["initial2"].Value; 22 | var firstName = $"{initial1}."; 23 | var middleName = $"{initial2}."; 24 | var lastName = match.Groups["last"].Value; 25 | var suffix = match.Groups["suffix"].Value; 26 | 27 | 28 | var scoreMod = 0; 29 | 30 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 31 | 32 | var pn = new ParsedFullName 33 | { 34 | FirstName = firstName, 35 | MiddleName = middleName, 36 | LastName = lastName, 37 | DisplayName = $"{firstName} {middleName} {lastName}", 38 | Suffix = suffix, 39 | Score = 100 + scoreMod 40 | }; 41 | return pn; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TwoInitialsFirstOptionalDotFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TwoInitialsFirstOptionalDotFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{TwoInitialFirstOptionalDot}{Space}(?\w+)$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var initial1 = match.Groups["initial1"].Value; 19 | var initial2 = match.Groups["initial2"].Value; 20 | var firstName = $"{initial1}."; 21 | var middleName = $"{initial2}."; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | 25 | var scoreMod = 0; 26 | 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Patterns/TwoInitialsSecondOptionalDotFirstLastPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using JetBrains.Annotations; 3 | using static BinaryFog.NameParser.RegexNameComponents; 4 | using static BinaryFog.NameParser.NameComponentSets; 5 | 6 | namespace BinaryFog.NameParser.Patterns 7 | { 8 | [UsedImplicitly] 9 | public class TwoInitialsSecondOptionalDotFirstLastPattern : IFullNamePattern 10 | { 11 | private static readonly string Pattern = $@"^{TwoInitialSecondOptionalDot}{Space}(?\w+)$"; 12 | private static readonly Regex Rx = new Regex(Pattern, CommonPatternRegexOptions); 13 | 14 | public ParsedFullName Parse(string rawName) 15 | { 16 | var match = Rx.Match(rawName); 17 | if (!match.Success) return null; 18 | var initial1 = match.Groups["initial1"].Value; 19 | var initial2 = match.Groups["initial2"].Value; 20 | var firstName = $"{initial1}."; 21 | var middleName = $"{initial2}."; 22 | var lastName = match.Groups["last"].Value; 23 | 24 | 25 | var scoreMod = 0; 26 | 27 | ModifyScoreExpectedLastName(ref scoreMod, lastName); 28 | 29 | var pn = new ParsedFullName 30 | { 31 | FirstName = firstName, 32 | MiddleName = middleName, 33 | LastName = lastName, 34 | DisplayName = $"{firstName} {middleName} {lastName}", 35 | Score = 100 + scoreMod 36 | }; 37 | return pn; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | 5 | 6 | // Setting ComVisible to false makes the types in this assembly not visible 7 | // to COM components. If you need to access a type in this assembly from 8 | // COM, set the ComVisible attribute to true on that type. 9 | [assembly: ComVisible(false)] 10 | 11 | // The following GUID is for the ID of the typelib if this project is exposed to COM 12 | [assembly: Guid("57a85560-8e76-45ae-b0ab-585c141bd889")] 13 | 14 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/RegexNameComponents.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace BinaryFog.NameParser 7 | { 8 | using static Helpers; 9 | 10 | public static class RegexNameComponents 11 | { 12 | public const string Space = @"(\s+|(?[a-z])\.?"; 17 | public const string Vowels = @"[aeiouy]"; 18 | 19 | public const string TwoInitial = 20 | @"(?[a-z])(?!" + Vowels + @")\." + OptionalSpace + @"(?[a-z])\."; 21 | 22 | public const string TwoInitialFirstOptionalDot = 23 | @"(?[a-z])(?!" + Vowels + @")\.?" + OptionalSpace + @"(?[a-z])\."; 24 | 25 | public const string TwoInitialSecondOptionalDot = 26 | @"(?[a-z])(?!" + Vowels + @")\." + OptionalSpace + @"(?[a-z])\.?"; 27 | 28 | public const string Name = @"'?(\w+|\w+('\w+)+)('(?=\W))?"; 29 | public const string First = @"(?" + Name + @")"; 30 | public const string AfricanFirst = @"(?" + Name + "'" + Name + @")"; 31 | public const string Last = @"(?" + Name + @")"; 32 | public const string Middle = @"(?" + Name + @")"; 33 | public const string TwoMiddle = @"(?" + Name + @")" + Space + @"(?" + Name + @")"; 34 | public const string Hyphen = "[-\u00AD\u058A\u1806\u2010\u2011\u30FB\uFE63\uFF0D\uFF65]"; 35 | public const string HyphenOptionallySpaced = OptionalSpace + Hyphen + OptionalSpace; 36 | public const string TwoHyphenOptionallySpacedMiddle = @"(?" + Name + @")" + HyphenOptionallySpaced + @"(?" + Name + @")"; 37 | 38 | public const string LastHyphenated = 39 | @"(?(?" + Name + @")" + HyphenOptionallySpaced + @"(?" + Name + @"))"; 40 | 41 | public const string SpaceOrHyphen = Space + "|" + HyphenOptionallySpaced; 42 | public const string Words = @"(\w+|" + SpaceOrHyphen + @")+"; 43 | 44 | public const string Nick = @"(\((?(" + Words + @"))\)|(?['""”“])(?(" + Words + 45 | @"))(?['""”“]))"; 46 | 47 | 48 | public const RegexOptions CommonPatternRegexOptions 49 | = RegexOptions.Compiled 50 | | RegexOptions.IgnoreCase 51 | | RegexOptions.Singleline 52 | | RegexOptions.CultureInvariant 53 | | RegexOptions.ExplicitCapture; 54 | 55 | public static readonly string LastNamePrefixes = RegexPipeJoin(Resources.LastNamePrefixes); 56 | public static readonly string PostNominals = RegexPipeJoin(Resources.PostNominals); // TODO: make use 57 | public static readonly string JobTitles = RegexPipeJoin(Resources.JobTitles); 58 | public static readonly string Suffixes = RegexPipeJoin(Resources.Suffixes); 59 | public static readonly string Titles = RegexPipeJoin(Resources.Titles); 60 | public static readonly string CompanySuffixes = RegexPipeJoin(Resources.CompanySuffixes); 61 | 62 | 63 | public static readonly string JobTitle = $@"(?{JobTitles})"; 64 | 65 | public static readonly string Title = $@"(?({Titles})((?!\s)\W)?)"; 66 | 67 | //public static readonly string Suffix = @"(?<suffix>((" + Suffixes + @")((?!\s)\W)?)([\s]*(?<=[\s\W]+)(" + PostNominals + @")((?!\s)\W)?)*?|([\s]*(?<=[\s\W]+)(" + PostNominals + @")((?!\s)\W)?))"; 68 | 69 | public static readonly string Suffix = $@"(?<suffix>({Suffixes})((?!\s)\W)?)"; 70 | public static readonly string Suffix1 = $@"(?<suffix1>({Suffixes})((?!\s)\W)?)"; 71 | public static readonly string Suffix2 = $@"(?<suffix2>({Suffixes})((?!\s)\W)?)"; 72 | 73 | public static readonly string Prefix = $@"(?<prefix>{LastNamePrefixes})"; 74 | 75 | /// <summary> 76 | /// Read and escape lines from a resource stream and combine 77 | /// them all together with pipe characters to create a string 78 | /// capable of being matched against when parsed as a <see cref="Regex" />. 79 | /// </summary> 80 | /// <param name="res">The resource stream containing strings as lines.</param> 81 | /// <returns>A <see cref="Regex" /> matchable concatenation of the resource.</returns> 82 | private static string RegexPipeJoin(Stream res) 83 | { 84 | // try to preallocate if stream length is known 85 | var resLength = checked((int) TryOrDefault(() => res!.Length)); 86 | var stringBuilder = resLength != 0 87 | ? new StringBuilder(resLength) 88 | : new StringBuilder(); 89 | using var reader = new StreamReader(res!); 90 | // first line case 91 | var line = reader.ReadLine(); 92 | 93 | Debug.Assert(line != null); 94 | stringBuilder.Append(Regex.Escape(line)); 95 | 96 | // second line 97 | line = reader.ReadLine(); 98 | while (line != null) 99 | { 100 | stringBuilder.Append('|') 101 | .Append(Regex.Escape(line)); 102 | 103 | // remaining lines 104 | line = reader.ReadLine(); 105 | } 106 | 107 | return stringBuilder.ToString(); 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | 5 | namespace BinaryFog.NameParser 6 | { 7 | public static class Resources { 8 | private static Type Type { get; } = typeof(Resources); 9 | 10 | public static string ResourceNamespace { get; } = Type?.FullName; 11 | public static Assembly Assembly { get; } = Type.GetTypeInfo()?.Assembly; 12 | 13 | private static Stream GetTxtStream(string name) { 14 | return Assembly?.GetManifestResourceStream($"{ResourceNamespace}.{name}.txt"); 15 | } 16 | 17 | public static Stream CompanySuffixes { get; } 18 | = GetTxtStream(nameof(CompanySuffixes)); 19 | 20 | public static Stream FemaleFirstNames { get; } 21 | = GetTxtStream(nameof(FemaleFirstNames)); 22 | 23 | public static Stream JobTitles { get; } 24 | = GetTxtStream(nameof(JobTitles)); 25 | 26 | public static Stream LastNamePrefixes { get; } 27 | = GetTxtStream(nameof(LastNamePrefixes)); 28 | 29 | public static Stream MaleFirstNames { get; } 30 | = GetTxtStream(nameof(MaleFirstNames)); 31 | 32 | public static Stream PostNominals { get; } 33 | = GetTxtStream(nameof(PostNominals)); 34 | 35 | public static Stream Suffixes { get; } 36 | = GetTxtStream(nameof(Suffixes)); 37 | 38 | public static Stream Titles { get; } 39 | = GetTxtStream(nameof(Titles)); 40 | 41 | public static Stream LastNames { get; } 42 | = GetTxtStream(nameof(LastNames)); 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/999230.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfog/NameParser/86d86190fb19b19cc96e046342bb31cac0f7d665/BinaryFog.NameParser/Resources/999230.jpg -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/CompanySuffixes.txt: -------------------------------------------------------------------------------- 1 | co 2 | company 3 | lt 4 | ltd 5 | llc 6 | limited 7 | inc 8 | incorporated 9 | corp 10 | corporation 11 | service 12 | services 13 | laboratories 14 | systems 15 | enterprises 16 | outfitters 17 | holdings -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/FemaleFirstNames.txt: -------------------------------------------------------------------------------- 1 | Emma 2 | Olivia 3 | Sophia 4 | Isabella 5 | Ava 6 | Mia 7 | Emily 8 | Abigail 9 | Madison 10 | Charlotte 11 | Harper 12 | Sofia 13 | Avery 14 | Elizabeth 15 | Amelia 16 | Evelyn 17 | Ella 18 | Chloe 19 | Victoria 20 | Aubrey 21 | Grace 22 | Zoey 23 | Natalie 24 | Addison 25 | Lillian 26 | Brooklyn 27 | Lily 28 | Hannah 29 | Layla 30 | Scarlett 31 | Aria 32 | Zoe 33 | Samantha 34 | Anna 35 | Leah 36 | Audrey 37 | Ariana 38 | Allison 39 | Savannah 40 | Arianna 41 | Camila 42 | Penelope 43 | Gabriella 44 | Claire 45 | Aaliyah 46 | Sadie 47 | Riley 48 | Skylar 49 | Nora 50 | Sarah 51 | Hailey 52 | Kaylee 53 | Paisley 54 | Kennedy 55 | Ellie 56 | Peyton 57 | Annabelle 58 | Caroline 59 | Madelyn 60 | Serenity 61 | Aubree 62 | Lucy 63 | Alexa 64 | Alexis 65 | Nevaeh 66 | Stella 67 | Violet 68 | Genesis 69 | Mackenzie 70 | Bella 71 | Autumn 72 | Mila 73 | Kylie 74 | Maya 75 | Piper 76 | Alyssa 77 | Taylor 78 | Eleanor 79 | Melanie 80 | Naomi 81 | Faith 82 | Eva 83 | Katherine 84 | Lydia 85 | Brianna 86 | Julia 87 | Ashley 88 | Khloe 89 | Madeline 90 | Ruby 91 | Sophie 92 | Alexandra 93 | London 94 | Lauren 95 | Gianna 96 | Isabelle 97 | Alice 98 | Vivian 99 | Hadley 100 | Jasmine 101 | Morgan 102 | Kayla 103 | Cora 104 | Bailey 105 | Kimberly 106 | Reagan 107 | Hazel 108 | Clara 109 | Sydney 110 | Trinity 111 | Natalia 112 | Valentina 113 | Rylee 114 | Jocelyn 115 | Maria 116 | Aurora 117 | Eliana 118 | Brielle 119 | Liliana 120 | Mary 121 | Elena 122 | Molly 123 | Makayla 124 | Lilly 125 | Andrea 126 | Quinn 127 | Jordyn 128 | Adalynn 129 | Nicole 130 | Delilah 131 | Kendall 132 | Kinsley 133 | Ariel 134 | Payton 135 | Paige 136 | Mariah 137 | Brooke 138 | Willow 139 | Jade 140 | Lyla 141 | Mya 142 | Ximena 143 | Luna 144 | Isabel 145 | Mckenzie 146 | Ivy 147 | Josephine 148 | Amy 149 | Laila 150 | Isla 151 | Eden 152 | Adalyn 153 | Angelina 154 | Londyn 155 | Rachel 156 | Melody 157 | Juliana 158 | Kaitlyn 159 | Brooklynn 160 | Destiny 161 | Emery 162 | Gracie 163 | Norah 164 | Emilia 165 | Reese 166 | Elise 167 | Sara 168 | Aliyah 169 | Margaret 170 | Catherine 171 | Vanessa 172 | Katelyn 173 | Gabrielle 174 | Arabella 175 | Valeria 176 | Valerie 177 | Adriana 178 | Everly 179 | Jessica 180 | Daisy 181 | Makenzie 182 | Summer 183 | Lila 184 | Rebecca 185 | Julianna 186 | Callie 187 | Michelle 188 | Ryleigh 189 | Presley 190 | Alaina 191 | Angela 192 | Alina 193 | Harmony 194 | Rose 195 | Athena 196 | Emerson 197 | Adelyn 198 | Alana 199 | Hayden 200 | Izabella 201 | Cali 202 | Marley 203 | Esther 204 | Fiona 205 | Stephanie 206 | Cecilia 207 | Kate 208 | Kinley 209 | Jayla 210 | Genevieve 211 | Alexandria 212 | Eliza 213 | Kylee 214 | Alivia 215 | Giselle 216 | Arya 217 | Alayna 218 | Leilani 219 | Adeline 220 | Jennifer 221 | Tessa 222 | Ana 223 | Finley 224 | Melissa 225 | Daniela 226 | Aniyah 227 | Daleyza 228 | Keira 229 | Charlie 230 | Lucia 231 | Hope 232 | Gabriela 233 | Mckenna 234 | Brynlee 235 | Parker 236 | Lola 237 | Amaya 238 | Miranda 239 | Maggie 240 | Anastasia 241 | Leila 242 | Lexi 243 | Georgia 244 | Kenzie 245 | Iris 246 | Jacqueline 247 | Jordan 248 | Cassidy 249 | Vivienne 250 | Camille 251 | Noelle 252 | Adrianna 253 | Teagan 254 | Josie 255 | Juliette 256 | Annabella 257 | Allie 258 | Juliet 259 | Kendra 260 | Sienna 261 | Brynn 262 | Kali 263 | Maci 264 | Danielle 265 | Haley 266 | Jenna 267 | Raelynn 268 | Delaney 269 | Paris 270 | Alexia 271 | Lyric 272 | Gemma 273 | Lilliana 274 | Chelsea 275 | Angel 276 | Evangeline 277 | Ayla 278 | Kayleigh 279 | Lena 280 | Katie 281 | Elaina 282 | Olive 283 | Madeleine 284 | Makenna 285 | Dakota 286 | Elsa 287 | Nova 288 | Nadia 289 | Alison 290 | Kaydence 291 | Journey 292 | Jada 293 | Kathryn 294 | Shelby 295 | Nina 296 | Elliana 297 | Diana 298 | Phoebe 299 | Alessandra 300 | Eloise 301 | Nyla 302 | Skyler 303 | Madilyn 304 | Adelynn 305 | Miriam 306 | Ashlyn 307 | Amiyah 308 | Megan 309 | Amber 310 | Rosalie 311 | Annie 312 | Lilah 313 | Charlee 314 | Amanda 315 | Ruth 316 | Adelaide 317 | June 318 | Laura 319 | Daniella 320 | Mikayla 321 | Raegan 322 | Jane 323 | Ashlynn 324 | Kelsey 325 | Erin 326 | Christina 327 | Joanna 328 | Fatima 329 | Allyson 330 | Talia 331 | Mariana 332 | Sabrina 333 | Haven 334 | Ainsley 335 | Cadence 336 | Elsie 337 | Leslie 338 | Heaven 339 | Arielle 340 | Maddison 341 | Alicia 342 | Briella 343 | Lucille 344 | Sawyer 345 | Malia 346 | Selena 347 | Heidi 348 | Kyleigh 349 | Harley 350 | Kira 351 | Lana 352 | Sierra 353 | Kiara 354 | Paislee 355 | Alondra 356 | Daphne 357 | Carly 358 | Jaylah 359 | Kyla 360 | Bianca 361 | Baylee 362 | Cheyenne 363 | Macy 364 | Camilla 365 | Catalina 366 | Gia 367 | Vera 368 | Skye 369 | Aylin 370 | Sloane 371 | Myla 372 | Yaretzi 373 | Giuliana 374 | Macie 375 | Veronica 376 | Esmeralda 377 | Lia 378 | Averie 379 | Addyson 380 | Kamryn 381 | Mckinley 382 | Ada 383 | Carmen 384 | Mallory 385 | Jillian 386 | Ariella 387 | Rylie 388 | Sage 389 | Abby 390 | Scarlet 391 | Logan 392 | Tatum 393 | Bethany 394 | Dylan 395 | Elle 396 | Jazmin 397 | Aspen 398 | Camryn 399 | Malaysia 400 | Haylee 401 | Nayeli 402 | Gracelyn 403 | Kamila 404 | Helen 405 | Marilyn 406 | April 407 | Carolina 408 | Amina 409 | Julie 410 | Raelyn 411 | Blakely 412 | Rowan 413 | Angelique 414 | Miracle 415 | Emely 416 | Jayleen 417 | Kennedi 418 | Amira 419 | Briana 420 | Gwendolyn 421 | Justice 422 | Zara 423 | Aleah 424 | Itzel 425 | Bristol 426 | Francesca 427 | Emersyn 428 | Aubrie 429 | Karina 430 | Nylah 431 | Kelly 432 | Anaya 433 | Maliyah 434 | Evelynn 435 | Ember 436 | Melany 437 | Angelica 438 | Jimena 439 | Madelynn 440 | Kassidy 441 | Tiffany 442 | Kara 443 | Jazmine 444 | Jayda 445 | Dahlia 446 | Alejandra 447 | Sarai 448 | Annabel 449 | Holly 450 | Janelle 451 | Braelyn 452 | Gracelynn 453 | River 454 | Viviana 455 | Serena 456 | Brittany 457 | Annalise 458 | Brinley 459 | Madisyn 460 | Eve 461 | Cataleya 462 | Joy 463 | Caitlyn 464 | Anabelle 465 | Emmalyn 466 | Journee 467 | Celeste 468 | Brylee 469 | Luciana 470 | Marlee 471 | Savanna 472 | Anya 473 | Marissa 474 | Jazlyn 475 | Zuri 476 | Kailey 477 | Crystal 478 | Michaela 479 | Lorelei 480 | Guadalupe 481 | Madilynn 482 | Maeve 483 | Hanna 484 | Priscilla 485 | Kyra 486 | Lacey 487 | Nia 488 | Charley 489 | Jamie 490 | Juniper 491 | Cynthia 492 | Karen 493 | Sylvia 494 | Phoenix 495 | Aleena 496 | Caitlin 497 | Felicity 498 | Elisa 499 | Julissa 500 | Rebekah 501 | Evie 502 | Helena 503 | Imani 504 | Karla 505 | Millie 506 | Lilian 507 | Raven 508 | Harlow 509 | Leia 510 | Ryan 511 | Kailyn 512 | Lillie 513 | Amara 514 | Kadence 515 | Lauryn 516 | Cassandra 517 | Kaylie 518 | Madalyn 519 | Anika 520 | Hayley 521 | Bria 522 | Colette 523 | Henley 524 | Amari 525 | Regina 526 | Alanna 527 | Azalea 528 | Fernanda 529 | Jaliyah 530 | Anabella 531 | Adelina 532 | Lilyana 533 | Skyla 534 | Addisyn 535 | Zariah 536 | Bridget 537 | Braylee 538 | Monica 539 | Jayden 540 | Leighton 541 | Gloria 542 | Johanna 543 | Addilyn 544 | Danna 545 | Selah 546 | Aryanna 547 | Kaylin 548 | Aniya 549 | Willa 550 | Angie 551 | Kaia 552 | Kaliyah 553 | Anne 554 | Tiana 555 | Charleigh 556 | Winter 557 | Danica 558 | Alayah 559 | Aisha 560 | Bailee 561 | Kenley 562 | Aileen 563 | Lexie 564 | Janiyah 565 | Braelynn 566 | Liberty 567 | Katelynn 568 | Mariam 569 | Sasha 570 | Lindsey 571 | Montserrat 572 | Cecelia 573 | Mikaela 574 | Kaelyn 575 | Rosemary 576 | Annika 577 | Tatiana 578 | Cameron 579 | Marie 580 | Dallas 581 | Virginia 582 | Liana 583 | Matilda 584 | Freya 585 | Lainey 586 | Hallie 587 | Jessie 588 | Audrina 589 | Blake 590 | Hattie 591 | Monserrat 592 | Kiera 593 | Laylah 594 | Greta 595 | Alyson 596 | Emilee 597 | Maryam 598 | Melina 599 | Dayana 600 | Jaelynn 601 | Beatrice 602 | Frances 603 | Elisabeth 604 | Saige 605 | Kensley 606 | Meredith 607 | Aranza 608 | Rosa 609 | Shiloh 610 | Charli 611 | Elyse 612 | Alani 613 | Mira 614 | Lylah 615 | Linda 616 | Whitney 617 | Alena 618 | Jaycee 619 | Joselyn 620 | Ansley 621 | Kynlee 622 | Miah 623 | Tenley 624 | Breanna 625 | Emelia 626 | Maia 627 | Edith 628 | Pearl 629 | Anahi 630 | Coraline 631 | Samara 632 | Demi 633 | Chanel 634 | Kimber 635 | Lilith 636 | Malaya 637 | Jemma 638 | Myra 639 | Bryanna 640 | Laney 641 | Jaelyn 642 | Kaylynn 643 | Kallie 644 | Natasha 645 | Nathalie 646 | Perla 647 | Amani 648 | Lilianna 649 | Madalynn 650 | Blair 651 | Elianna 652 | Karsyn 653 | Lindsay 654 | Elaine 655 | Dulce 656 | Ellen 657 | Erica 658 | Maisie 659 | Renata 660 | Kiley 661 | Marina 662 | Remi 663 | Emmy 664 | Ivanna 665 | Amirah 666 | Livia 667 | Amelie 668 | Irene 669 | Mabel 670 | Milan 671 | Armani 672 | Cara 673 | Ciara 674 | Kathleen 675 | Jaylynn 676 | Caylee 677 | Lea 678 | Erika 679 | Paola 680 | Alma 681 | Courtney 682 | Mae 683 | Kassandra 684 | Maleah 685 | Remington 686 | Leyla 687 | Mina 688 | Ariah 689 | Christine 690 | Jasmin 691 | Kora 692 | Chaya 693 | Karlee 694 | Lailah 695 | Mara 696 | Jaylee 697 | Raquel 698 | Siena 699 | Lennon 700 | Desiree 701 | Hadassah 702 | Kenya 703 | Aliana 704 | Wren 705 | Amiya 706 | Isis 707 | Zaniyah 708 | Avah 709 | Amia 710 | Cindy 711 | Eileen 712 | Kayden 713 | Madyson 714 | Celine 715 | Aryana 716 | Everleigh 717 | Isabela 718 | Reyna 719 | Teresa 720 | Jolene 721 | Marjorie 722 | Myah 723 | Clare 724 | Claudia 725 | Leanna 726 | Noemi 727 | Corinne 728 | Simone 729 | Alia 730 | Brenda 731 | Dorothy 732 | Emilie 733 | Elin 734 | Tori 735 | Martha 736 | Ally 737 | Arely 738 | Leona 739 | Patricia 740 | Sky 741 | Thalia 742 | Carolyn 743 | Emory 744 | Nataly 745 | Paityn 746 | Shayla 747 | Averi 748 | Jazlynn 749 | Margot 750 | Lisa 751 | Lizbeth 752 | Nancy 753 | Deborah 754 | Ivory 755 | Khaleesi 756 | Elliot 757 | Meadow 758 | Yareli 759 | Farrah 760 | Milania 761 | Janessa 762 | Milana 763 | Zoie 764 | Adele 765 | Clarissa 766 | Hunter 767 | Lina 768 | Oakley 769 | Sariah 770 | Emmalynn 771 | Galilea 772 | Hailee 773 | Halle 774 | Sutton 775 | Giana 776 | Thea 777 | Denise 778 | Naya 779 | Kristina 780 | Liv 781 | Nathaly 782 | Wendy 783 | Aubrielle 784 | Brenna 785 | Carter 786 | Danika 787 | Monroe 788 | Celia 789 | Dana 790 | Jolie 791 | Taliyah 792 | Casey 793 | Miley 794 | Yamileth 795 | Jaylene 796 | Saylor 797 | Joyce 798 | Milena 799 | Zariyah 800 | Sandra 801 | Ariadne 802 | Aviana 803 | Mollie 804 | Cherish 805 | Alaya 806 | Asia 807 | Nola 808 | Penny 809 | Dixie 810 | Marisol 811 | Adrienne 812 | Rylan 813 | Kori 814 | Kristen 815 | Aimee 816 | Esme 817 | Laurel 818 | Aliza 819 | Roselyn 820 | Sloan 821 | Lorelai 822 | Jenny 823 | Katalina 824 | Lara 825 | Amya 826 | Ayleen 827 | Aubri 828 | Ariya 829 | Carlee 830 | Iliana 831 | Magnolia 832 | Aurelia 833 | Elliott 834 | Evalyn 835 | Natalee 836 | Rayna 837 | Heather 838 | Collins 839 | Estrella 840 | Rory 841 | Hana 842 | Kenna 843 | Jordynn 844 | Rosie 845 | Aiyana 846 | America 847 | Angeline 848 | Janiya 849 | Jessa 850 | Tegan 851 | Susan 852 | Emmalee 853 | Taryn 854 | Temperance 855 | Alissa 856 | Kenia 857 | Abbigail 858 | Briley 859 | Kailee 860 | Zaria 861 | Chana 862 | Lillianna 863 | Barbara 864 | Carla 865 | Aliya 866 | Bonnie 867 | Keyla 868 | Marianna 869 | Paloma 870 | Jewel 871 | Joslyn 872 | Saniyah 873 | Audriana 874 | Giovanna 875 | Hadleigh 876 | Mckayla 877 | Jaida 878 | Salma 879 | Sharon 880 | Emmaline 881 | Kimora 882 | Wynter 883 | Avianna 884 | Amalia 885 | Karlie 886 | Kaidence 887 | Kairi 888 | Libby 889 | Sherlyn 890 | Diamond 891 | Holland 892 | Zendaya 893 | Mariyah 894 | Zainab 895 | Alisha 896 | Ayanna 897 | Ellison 898 | Harlee 899 | Lilyanna 900 | Bryleigh 901 | Julianne 902 | Kaleigh 903 | Miya 904 | Yasmin 905 | Anniston 906 | Estelle 907 | Emmeline 908 | Faye 909 | Kiana 910 | Anabel 911 | Zion 912 | Tara 913 | Astrid 914 | Emerie 915 | Sidney 916 | Zahra 917 | Jaylin 918 | Kinslee 919 | Tabitha 920 | Aubriella 921 | Addilynn 922 | Alyvia 923 | Hadlee 924 | Ingrid 925 | Lilia 926 | Macey 927 | Azaria 928 | Kaitlynn 929 | Neriah 930 | Annabell 931 | Ariyah 932 | Janae 933 | Kaiya 934 | Reina 935 | Rivka 936 | Alisa 937 | Marleigh 938 | Alisson 939 | Maliah 940 | Mercy 941 | Noa 942 | Scarlette 943 | Clementine 944 | Frida 945 | Ann 946 | Sonia 947 | Alannah 948 | Avalynn 949 | Dalia 950 | Ayva 951 | Stevie 952 | Judith 953 | Paulina 954 | Azariah 955 | Estella 956 | Remy 957 | Gwen 958 | Mattie 959 | Milani 960 | Raina 961 | Julieta 962 | Renee 963 | Lesly 964 | Abrielle 965 | Bryn 966 | Carlie 967 | Riya 968 | Karter 969 | Abril 970 | Aubrianna 971 | Jocelynn 972 | Kylah 973 | Louisa 974 | Pyper 975 | Antonia 976 | Magdalena 977 | Moriah 978 | Ryann 979 | Tamia 980 | Kailani 981 | Landry 982 | Aya 983 | Ireland 984 | Mercedes 985 | Rosalyn 986 | Alaysia 987 | Annalee 988 | Patience 989 | Aanya 990 | Paula 991 | Samiyah 992 | Yaritza 993 | Cordelia 994 | Micah 995 | Nala 996 | Belen 997 | Cambria 998 | Natalya 999 | Kaelynn 1000 | Kai 1001 | Marjolaine 1002 | Celina 1003 | Pam 1004 | Ginette 1005 | Jody 1006 | Isa 1007 | Delores -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/JobTitles.txt: -------------------------------------------------------------------------------- 1 | accounts payable 2 | accounts receivable 3 | assistant manager 4 | chairman 5 | chief accounting officer 6 | chief administrative officer 7 | chief communications officer 8 | chief creative officer 9 | chief data officer 10 | chief diversity officer 11 | chief engineering officer 12 | chief executive officer 13 | chief financial officer 14 | chief information officer 15 | chief legal officer 16 | chief marketing officer 17 | chief networking officer 18 | chief operations officer 19 | chief quality officer 20 | chief research officer 21 | chief risk officer 22 | chief science officer 23 | chief security officer 24 | chief strategy officer 25 | chief technology officer 26 | department head 27 | deputy general manager 28 | deputy president 29 | doctor 30 | executing director 31 | executive chairman 32 | executive director 33 | executive vice president 34 | general manager 35 | managing director 36 | payroll 37 | president 38 | section head 39 | senator 40 | senior executive vice president 41 | senior vice president 42 | supervisor 43 | treasurer 44 | vice chairman 45 | vice president 46 | senator -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/LastNamePrefixes.txt: -------------------------------------------------------------------------------- 1 | 's 2 | 't 3 | a 4 | aan 5 | aan 't 6 | aan de 7 | aan den 8 | aan der 9 | aan het 10 | af 11 | al 12 | am 13 | am de 14 | auf 15 | auf 'm 16 | auf dem 17 | auf den 18 | auf der 19 | auf ter 20 | aus 21 | aus dem 22 | ben 23 | bij 24 | bij 't 25 | bij de 26 | bij den 27 | bij het 28 | bin 29 | boven 'd 30 | d' 31 | da 32 | dal 33 | dalla 34 | das 35 | de 36 | de die 37 | de die le 38 | de l' 39 | de la 40 | de le 41 | de ter 42 | de van der 43 | deca 44 | degli 45 | dei 46 | del 47 | dela 48 | della 49 | den 50 | der 51 | des 52 | di 53 | die 54 | die le 55 | do 56 | don 57 | dos 58 | du 59 | el 60 | i 61 | im 62 | in 63 | in 't 64 | in de 65 | in den 66 | in der 67 | in het 68 | l 69 | l' 70 | la 71 | las 72 | le 73 | les 74 | lo 75 | los 76 | met den op 77 | on der 78 | onder 79 | op 80 | op 't 81 | op de 82 | op den 83 | op der 84 | op het 85 | op ten 86 | opde 87 | opden 88 | over 89 | over 't 90 | over de 91 | over den 92 | over het 93 | s' 94 | t' 95 | te 96 | ten 97 | ter 98 | thoe 99 | to 100 | toe 101 | uijt 102 | uit 103 | uit den 104 | unter 105 | uut 't 106 | uut den 107 | uyt den 108 | uyter 109 | van 110 | van 's 111 | van 't 112 | van de 113 | van de l' 114 | van den 115 | van der 116 | van gen 117 | van het 118 | van la 119 | van t' 120 | van ter 121 | vande 122 | vanden 123 | vander 124 | ver 125 | vom 126 | von 127 | von 't 128 | von dem 129 | von den 130 | von der 131 | voor 132 | vor 133 | vor der 134 | zu 135 | zum 136 | zur -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/MaleFirstNames.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binaryfog/NameParser/86d86190fb19b19cc96e046342bb31cac0f7d665/BinaryFog.NameParser/Resources/MaleFirstNames.txt -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/PostNominals.txt: -------------------------------------------------------------------------------- 1 | (ret) 2 | (ret.) 3 | a de c 4 | adc 5 | adcp 6 | adv 7 | afm 8 | am 9 | aoe 10 | ara 11 | arrc 12 | ba 13 | bchd 14 | bd 15 | bds 16 | bdsc 17 | bem 18 | bohdsc 19 | bt 20 | btss 21 | cb 22 | cbe 23 | cc 24 | cd 25 | cfd 26 | cgm 27 | cj 28 | cja 29 | cjc 30 | cm 31 | cmm 32 | com 33 | cp 34 | cq 35 | cr 36 | csm 37 | csyp 38 | cv 39 | cvo 40 | dbci 41 | dbe 42 | dc 43 | dcm 44 | dd 45 | dds 46 | ddsc 47 | dfc 48 | dfm 49 | dl 50 | dmd 51 | dmsc 52 | do 53 | dpm 54 | dpt 55 | dsm 56 | dvm 57 | esq 58 | fcps 59 | frcp 60 | frgs 61 | frs 62 | frsc 63 | gbe 64 | gm 65 | goq 66 | iso 67 | j 68 | ja 69 | jd 70 | jp 71 | kbe 72 | lvo 73 | ma 74 | mb 75 | mbe 76 | mc 77 | md 78 | mds 79 | mdsc 80 | mha 81 | mhl 82 | mla 83 | mm 84 | mmm 85 | mmp 86 | mmsc 87 | mmv 88 | mna 89 | mom 90 | mp 91 | mpp 92 | mrsc 93 | ms 94 | msc 95 | mscds 96 | msd 97 | msm 98 | msp 99 | mvo 100 | obc 101 | obe 102 | oc 103 | od 104 | om 105 | omm 106 | onb 107 | onl 108 | ons 109 | oom 110 | oont 111 | opei 112 | oq 113 | pc 114 | phd 115 | prov j 116 | psp 117 | qc 118 | qgm 119 | qhc 120 | qhds 121 | qhno 122 | qhns 123 | qhp 124 | qhs 125 | qpo 126 | raf 127 | ret 128 | rm 129 | rmc 130 | rmp 131 | rn 132 | rvm 133 | sc 134 | scd 135 | smv 136 | som 137 | ssf 138 | thd 139 | usa 140 | usaf 141 | usgc 142 | usmc 143 | usn 144 | vc 145 | vmd 146 | vr 147 | ws 148 | md 149 | ca 150 | cpa 151 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/Suffixes.txt: -------------------------------------------------------------------------------- 1 | i 2 | ii 3 | iii 4 | iv 5 | v 6 | vi 7 | vii 8 | viii 9 | ix 10 | x 11 | xi 12 | xii 13 | xiii 14 | xiv 15 | xv 16 | xvi 17 | xvii 18 | xviii 19 | xix 20 | jr 21 | sr 22 | esq 23 | jr. 24 | sr. 25 | esq. 26 | esquire 27 | -------------------------------------------------------------------------------- /BinaryFog.NameParser/Resources/Titles.txt: -------------------------------------------------------------------------------- 1 | dame 2 | dr 3 | madam 4 | madame 5 | miss 6 | missus 7 | mistress 8 | mr 9 | mrs 10 | ms 11 | mx 12 | prof 13 | sir 14 | master 15 | mz 16 | lord 17 | lady 18 | hon 19 | honorable 20 | right hon 21 | fr 22 | rev 23 | revd 24 | cpt 25 | lt 26 | sgt 27 | sen 28 | rep 29 | commish -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 BinaryFog.com 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NameParser 2 | ==== 3 | 4 | [![Join the chat at https://gitter.im/binaryfog/NameParser](https://badges.gitter.im/binaryfog/NameParser.svg)](https://gitter.im/binaryfog/NameParser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | 7 | Parses names using English conventions for persons names. 8 | Intended to be extendable, the library can be extended just by implement `IFullNamePattern` interface and assign a score to the returned result. 9 | 10 | For the sake of performance, the assembly and types implementing `IFullNamePattern` must be loaded before the first attempt to use the `NameParser`. 11 | 12 | If you have a person name that is not parsed correctly, please post a message on https://gitter.im/binaryfog/NameParser. I'll see what I can do. 13 | 14 | Usage: 15 | ```csharp 16 | string fullName = "Mr. Jack Johnson"; 17 | FullNameParser target = new FullNameParser(fullName); 18 | target.Parse(); 19 | string firstName = target.FirstName; 20 | string middleName = target.MiddleName; 21 | string lastName = target.LastName; 22 | string title = target.Title; 23 | string nickName = target.NickName; 24 | string suffix = target.Suffix; 25 | string displayName = target.DisplayName; 26 | ``` 27 | 28 | Alternative usage: 29 | ```csharp 30 | string fullName = "Mr. Jack Johnson"; 31 | FullNameParser target = FullNameParser.Parse(fullName); 32 | string firstName = target.FirstName; 33 | string middleName = target.MiddleName; 34 | string lastName = target.LastName; 35 | string title = target.Title; 36 | string nickName = target.NickName; 37 | string suffix = target.Suffix; 38 | string displayName = target.DisplayName; 39 | ``` 40 | Jun. 17, 2017: Started a new related project Nameparser.Dataset on github as a repository for names and parsed names. Feel free to add there names and parsed names. 41 | 42 | Nov. 13 2015: More cases are now handled. These are the cases: 43 | * SR. John Henry William dela Vega, Jr Esq. 44 | * MANUEL ESQUIPULAS SOHOM 45 | * Maria Delores Esquivel-Moreno 46 | * PHILIP DEHART ESQ 47 | * DEHART, PHILIP 48 | * john 'jack' kennedy 49 | * john(jack) f kennedy 50 | * kennedy, john(jack) f 51 | * Mr.Jack Johnson, ESQ" 52 | * Jose Miguel De La Vega 53 | 54 | Jan. 8 2016: 100% code coverage. More test cases. These are the cases: 55 | * Empty string and white space cases. 56 | * Mr. Jack Francis Van Der Waal Sr. 57 | * Mr. Jack Francis Marion Van Der Waal Sr. 58 | --------------------------------------------------------------------------------