
后端數(shù)據(jù)工程【免費下載鏈接】CsvHelperLibrary to help reading and writing CSV files項目地址https://gitcode.com/gh_mirrors/cs/CsvHelper點擊查看免費下載導讀現(xiàn)實世界中的 CSV 數(shù)據(jù)并非總是擁有唯一表頭當同一列名在首行出現(xiàn)多次例如Name,Name表示 first name 與 last name 兩列時CsvHelper 默認無法區(qū)分它們。本指南圍繞倉庫文檔 mapping-duplicate-names/index.md 講解如何通過名稱索引Name Index解決這一場景你將掌握NameIndex()映射 API、[NameIndex]特性以及背后的GetFieldIndex索引解析原理并能正確處理讀、寫兩側(cè)的同名列映射。什么是名稱索引Name Index核心概念只有一句話名稱索引指的是同名表頭出現(xiàn)的第幾次第 0 次、第 1 次……而不是該列在整個 CSV 中的物理位置。例如下列數(shù)據(jù)Id,Name,Name 1,first,last兩列Name的物理位置分別是索引 1 和索引 2但它們的名稱索引分別是0和1——因為第一個Name是第 0 次出現(xiàn)第二個Name是第 1 次出現(xiàn)。這是 CsvHelper 判斷同名表頭時使用的計數(shù)口徑與列號無關。使用 ClassMap 映射同名表頭官方示例通過ClassMapT完成映射。為了讓它能直接運行這里補全了缺失的using并修正了原文檔示例中的筆誤{ get set; }缺少分號、混用 Tab/空格縮進using System.Globalization; using System.IO; using CsvHelper; using CsvHelper.Configuration; void Main() { using (var reader new StreamReader(path\\to\\file.csv)) using (var csv new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMapFooMap(); var records csv.GetRecordsFoo(); } } public class Foo { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public sealed class FooMap : ClassMapFoo { public FooMap() { Map(m m.Id); Map(m m.FirstName).Name(Name).NameIndex(0); Map(m m.LastName).Name(Name).NameIndex(1); } }要點拆解Map(m m.FirstName).Name(Name)與Map(m m.LastName).Name(Name)都聲明列名是Name.NameIndex(0)把FirstName綁定到第一次出現(xiàn)的Name列即數(shù)據(jù)行中的first.NameIndex(1)把LastName綁定到第二次出現(xiàn)的Name列即數(shù)據(jù)行中的last。注意Name和NameIndex必須成對使用才有效NameIndex的意義是在名為X的表頭中取第N個單獨使用NameIndex而沒有設置名稱時沒有任何定位作用。用 [NameIndex] 特性直接標注屬性如果不寫 ClassMap也可以直接在屬性上使用CsvHelper.Configuration.Attributes.NameIndex特性。倉庫測試 NameIndexTests.cs 提供了等價寫法using System.Globalization; using System.IO; using System.Linq; using CsvHelper; using CsvHelper.Configuration.Attributes; private class NameIndexClass { public int Id { get; set; } [NameIndex(1)] public string? Name { get; set; } } using (var reader new StringReader(Id,Name,Name\r\n1,one,two\r\n)) using (var csv new CsvReader(reader, CultureInfo.InvariantCulture)) { var records csv.GetRecordsNameIndexClass().ToList(); // records[0].Id 1 // records[0].Name two綁定到第二個 Name 列 }從特性源碼 NameIndexAttribute.cs 可以看到該特性聲明為AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter同時實現(xiàn)了IMemberMapper與IParameterMapper并通過ApplyTo把值寫入memberMap.Data.NameIndex/parameterMap.Data.NameIndex。這意味著它不僅能用于屬性和字段也能用于構造函數(shù)參數(shù)的映射倉庫中存在對應的NameIndexAttributeTests.cs與NameIndexMapTests.cs測試用例例如通過參數(shù)映射把一個同名表頭列注入構造函數(shù)參數(shù)。寫入場景同名列頭也能按 NameIndex 輸出NameIndex同樣作用于寫入過程。在 CsvWriterMappingTests.cs 中可以看到一個多個屬性映射到同一個列名的寫入用例private sealed class SameNameMultipleTimesClassMap : ClassMapSameNameMultipleTimesClass { public SameNameMultipleTimesClassMap() { Map(m m.Name1).Name(ColumnName).NameIndex(1); Map(m m.Name2).Name(ColumnName).NameIndex(2); Map(m m.Name3).Name(ColumnName).NameIndex(0); } }注意這里 NameIndex 的取值1、2、0是亂序的這恰好印證了名稱索引是第幾次出現(xiàn)而非寫入順序?qū)懭霑r CsvHelper 會按 NameIndex 的排序輸出列最終表頭仍是ColumnName,ColumnName,ColumnName三列且列順序按名稱索引排序。源碼原理GetFieldIndex 如何定位同名表頭閱讀階段最終都由 CsvReader.cs 的GetFieldIndex方法完成解析其核心邏輯如下前置校驗如果沒有 header record或尚未調(diào)用ReadHeader()直接拋出ReaderException遍歷候選名稱對names參數(shù)即Name()指定的一個或多個名稱逐個經(jīng)PrepareHeaderForMatch處理在namedIndexes字典中查找第一個命中的名稱校驗名稱索引存在性if (name null || index namedIndexes[name].Count)說明第index次出現(xiàn)的同名表頭不存在——這是字段缺失當非isTryGet且非 optional 時會觸發(fā)MissingFieldFound委托回調(diào)見 CsvReader.cs隨后返回-1結果緩存命中后將nameKey string.Join(_, names) index寫入namedIndexCache避免重復遍歷。注釋明確指出該緩存對使用ConvertUsing的映射有顯著加速返回物理列索引return namedIndexes[name][index]——取的是該名稱第index次出現(xiàn)對應的真實列位置。namedIndexes本質(zhì)上是一個名稱 → 該名稱所有出現(xiàn)位置的列表的索引表因此同名表頭無論出現(xiàn)幾次都能通過index精確命中某一列。這正是名稱索引計數(shù)法與物理列號兩種口徑的最終交匯點映射時給的是名稱索引解析時換算回列位置。邊界情況與注意事項索引越界即字段缺失如果 CSV 中Name只出現(xiàn) 1 次而你映射了NameIndex(1)GetFieldIndex會判定字段缺失并觸發(fā)MissingFieldFound默認拋出MissingFieldException??赏ㄟ^配置MissingFieldFound委托自定義處理邏輯參考 Delegates/MissingFieldFound.cs。索引從 0 開始第一個同名表頭的 NameIndex 是0這與多數(shù)程序語言數(shù)組下標習慣一致但和第 1 列的人類直覺不同容易踩坑。默認索引為 0GetFieldIndex(string name, int index 0, ...)中 index 默認為0所以單表頭場景下不寫NameIndex也能取到第一個匹配列只有出現(xiàn)重復名稱時才必須顯式區(qū)分。無表頭記錄時不可用名稱索引依賴表頭行定位若配置了HasHeaderRecord false無表頭應改用Index()按物理列號映射參見同目錄下的 mapping-by-index 示例。與替代名稱Name(a, b)的關系Name支持傳入多個候選名解析時按聲明順序取第一個命中的名稱NameIndex作用于最終命中的那個名稱兩者可以組合使用以實現(xiàn)多個別名 同名多次出現(xiàn)的復雜表頭。小結處理重復表頭是 CSV 數(shù)據(jù)清洗中的高頻場景。CsvHelper 通過名稱索引這一計數(shù)口徑把第 N 次出現(xiàn)的某列從同名表頭中精確分離出來讀側(cè)由GetFieldIndex在namedIndexes索引表中完成換算寫側(cè)按名稱索引排序輸出既可以用ClassMap的.Name().NameIndex()鏈式調(diào)用也可以用[NameIndex]特性直標屬性還可用于構造函數(shù)參數(shù)映射。把握NameIndex 是第幾次出現(xiàn)、而非列位置這一核心語義即可在各種同名表頭的數(shù)據(jù)上寫出清晰、可維護的映射配置。贊分享后端數(shù)據(jù)工程【免費下載鏈接】CsvHelperLibrary to help reading and writing CSV files項目地址https://gitcode.com/gh_mirrors/cs/CsvHelper點擊查看免費下載相關推薦KLayout中數(shù)字開頭的圖層名稱映射問題解析KLayout中數(shù)字開頭的圖層名稱映射問題解析 在使用KLayout進行版圖設計時圖層名稱通常以字母開頭但在某些特殊情況下如使用特定工藝設計套件PDK時硬件開發(fā)桌面應用圖形學0168. Excel 表列名稱解析LeetCode 經(jīng)典進制轉(zhuǎn)換與字符映射題解0168. Excel 表列名稱解析LeetCode 經(jīng)典進制轉(zhuǎn)換與字符映射題解 本篇指南基于「算法通關手冊」AlgoNote倉庫中的 0168. Exc教程文檔知識庫上一篇SLIP線性探針Linear Probe實戰(zhàn)遷移學習性能優(yōu)化的10個技巧下一篇wiliwili B站客戶端在 Switch 大氣層上怎么裝桌面圖標、黑屏、連不上網(wǎng)一次說清創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考