v9.10.2019.0101 全面巩固批量Insert/Update/Upsert,支持数据备份、恢复和同步,支持实体列表保存到文件以及加载
|
# Æ´Òô¿â PinYin
## ¸ÅÊö
`PinYin` ÊÇ NewLife.Core Öеĺº×ÖÆ´Òôת»»¹¤¾ßÀ࣬Ìṩ¸ßЧµÄºº×ÖתƴÒô¹¦ÄÜ¡£Ö§³Ö GB2312 Ò»¼¶ºÍ¶þ¼¶ºº×Ö£¬Äܹ»»ñÈ¡ºº×ÖµÄȫƴ»òÆ´ÒôÊ××Öĸ£¬ÊÊÓÃÓÚËÑË÷¡¢ÅÅÐò¡¢ÊäÈë·¨µÈ³¡¾°¡£
**ÃüÃû¿Õ¼ä**£º`NewLife.Common`
**ÎĵµµØÖ·**£ºhttps://newlifex.com/core/pinyin
## ºËÐÄÌØÐÔ
- **¸ßÐÔÄÜ**£º»ùÓÚ GB2312 ±àÂëºÍÇøÎ»ÂëËã·¨£¬ÎÞÐè¼ÓÔØ´óÐÍ×ÖµäÎļþ
- **È«ºº×ÖÖ§³Ö**£º¸²¸Ç GB2312 Ò»¼¶ºº×Ö£¨3755¸ö£©ºÍ¶þ¼¶ºº×Ö£¨3008¸ö£©
- **¶àÖÖÊä³ö**£ºÖ§³Öȫƴ¡¢Ê××Öĸ¡¢µ¥×ÖÆ´ÒôµÈ¶àÖÖÐÎʽ
- **ÇáÁ¿¼¶**£ºÎÞÍⲿÒÀÀµ£¬´¿Ë㷨ʵÏÖ
- **ÌØÊâ´¦Àí**£ºÖ§³Ö"ÖØÇì"µÈ¶àÒô×ֵij£¼û¶ÁÒô
## ¿ìËÙ¿ªÊ¼
```csharp
using NewLife.Common;
// »ñÈ¡µ¥×ÖÆ´Òô
var py = PinYin.Get('ÖÐ'); // "Zhong"
// »ñÈ¡×Ö·û´®È«Æ´
var fullPy = PinYin.Get("ÐÂÉúÃü"); // "XinShengMing"
// »ñȡƴÒôÊ××Öĸ
var first = PinYin.GetFirst("ÐÂÉúÃü"); // "XSM"
// »ñȡƴÒôÊý×é
var arr = PinYin.GetAll("ÄãºÃ"); // ["Ni", "Hao"]
```
## API ²Î¿¼
### Get£¨µ¥×ÖÆ´Òô£©
```csharp
public static String Get(Char ch)
```
»ñÈ¡µ¥¸öºº×ֵį´Òô¡£
**²ÎÊý˵Ã÷**£º
- `ch`£ºÒª×ª»»µÄ×Ö·û
**·µ»ØÖµ**£º
- ºº×Ö·µ»ØÊ××Öĸ´óдµÄÆ´Òô£¨Èç "Zhong"£©
- À¶¡×Ö·û¡¢±êµã¡¢·ÇÖÐÎÄ×Ö·ûÔÑù·µ»Ø
- ÎÞ·¨Ê¶±ðµÄºº×Ö·µ»Ø¿Õ×Ö·û´®
**ʾÀý**£º
```csharp
PinYin.Get('ÖÐ') // "Zhong"
PinYin.Get('¹ú') // "Guo"
PinYin.Get('A') // "A"
PinYin.Get('£¬') // "£¬"
PinYin.Get('¢Ù') // "¢Ù"
```
### Get£¨×Ö·û´®È«Æ´£©
```csharp
public static String Get(String str)
```
»ñÈ¡×Ö·û´®µÄÍêÕûÆ´Òô£¬¸÷×ÖÆ´ÒôÖ±½ÓÁ¬½Ó¡£
**ʾÀý**£º
```csharp
PinYin.Get("Öйú") // "ZhongGuo"
PinYin.Get("ÐÂÉúÃüÍŶÓ") // "XinShengMingTuanDui"
PinYin.Get("HelloÊÀ½ç") // "HelloShiJie"
```
### GetAll
```csharp
public static String[] GetAll(String str)
```
»ñÈ¡×Ö·û´®ÖÐÿ¸ö×Ö·ûµÄÆ´Òô£¬·µ»Ø×Ö·û´®Êý×é¡£
**ÌØÊâ´¦Àí**£º
- "ÖØÇì" ÌØÊâ´¦ÀíΪ ["Chong", "Qing"]
**ʾÀý**£º
```csharp
PinYin.GetAll("ÄãºÃ") // ["Ni", "Hao"]
PinYin.GetAll("ÖØÇì") // ["Chong", "Qing"]
PinYin.GetAll("ABC") // ["A", "B", "C"]
PinYin.GetAll("Hello") // ["H", "e", "l", "l", "o"]
```
### GetFirst£¨Æ´ÒôÊ××Öĸ£©
```csharp
public static Char GetFirst(Char ch)
public static String GetFirst(String str)
```
»ñÈ¡ºº×Ö»ò×Ö·û´®µÄÆ´ÒôÊ××Öĸ¡£
**ʾÀý**£º
```csharp
// µ¥×ÖÊ××Öĸ
PinYin.GetFirst('ÖÐ') // 'Z'
PinYin.GetFirst('¹ú') // 'G'
PinYin.GetFirst('A') // 'A'
// ×Ö·û´®Ê××Öĸ
PinYin.GetFirst("ÐÂÉúÃü") // "XSM"
PinYin.GetFirst("Öйú") // "ZG"
PinYin.GetFirst("Hello") // "Hello"
```
## ʹÓó¡¾°
### 1. ËÑË÷Æ¥Åä
```csharp
public class UserService
{
/// <summary>¸ù¾ÝÆ´ÒôÊ××ÖĸËÑË÷Óû§</summary>
public List<User> SearchByPinyin(List<User> users, String keyword)
{
var upperKeyword = keyword.ToUpper();
return users.Where(u =>
{
// È«ÃûÆ¥Åä
if (u.Name.Contains(keyword, StringComparison.OrdinalIgnoreCase))
return true;
// Æ´ÒôÊ××ÖĸƥÅä
var firstLetters = PinYin.GetFirst(u.Name);
return firstLetters.Contains(upperKeyword, StringComparison.OrdinalIgnoreCase);
}).ToList();
}
}
// ʹÓÃʾÀý
var users = new List<User>
{
new User { Name = "ÕÅÈý" },
new User { Name = "ÀîËÄ" },
new User { Name = "ÍõÎå" }
};
var result = service.SearchByPinyin(users, "ZS"); // ÕÒµ½ "ÕÅÈý"
var result2 = service.SearchByPinyin(users, "LS"); // ÕÒµ½ "ÀîËÄ"
```
### 2. °´Æ´ÒôÅÅÐò
```csharp
public class ProductSorter
{
/// <summary>°´Æ´ÒôÅÅÐòÉÌÆ·Ãû³Æ</summary>
public List<Product> SortByPinyin(List<Product> products)
{
return products
.OrderBy(p => PinYin.Get(p.Name))
.ToList();
}
}
// ʹÓÃʾÀý
var products = new List<Product>
{
new Product { Name = "Æ»¹û" },
new Product { Name = "Ïã½¶" },
new Product { Name = "³È×Ó" }
};
var sorted = sorter.SortByPinyin(products);
// ÅÅÐò½á¹û£º³È×Ó(ChengZi) -> Æ»¹û(PingGuo) -> Ïã½¶(XiangJiao)
```
### 3. Éú³ÉÆ´ÒôË÷Òý
```csharp
public class ContactIndexer
{
/// <summary>Éú³ÉÁªÏµÈËÆ´ÒôË÷Òý</summary>
public Dictionary<Char, List<Contact>> BuildIndex(List<Contact> contacts)
{
var index = new Dictionary<Char, List<Contact>>();
foreach (var contact in contacts)
{
var firstLetter = PinYin.GetFirst(contact.Name[0]);
if (!index.ContainsKey(firstLetter))
index[firstLetter] = new List<Contact>();
index[firstLetter].Add(contact);
}
return index;
}
}
// ʹÓÃʾÀý
var contacts = new List<Contact>
{
new Contact { Name = "ÕÅÈý" },
new Contact { Name = "ÕÔËÄ" },
new Contact { Name = "ÀîÎå" }
};
var index = indexer.BuildIndex(contacts);
// index['Z'] = [ÕÅÈý, ÕÔËÄ]
// index['L'] = [ÀîÎå]
```
### 4. ÊäÈë·¨Ìáʾ
```csharp
public class InputSuggestion
{
private readonly List<String> _words;
public InputSuggestion(List<String> words)
{
_words = words;
}
/// <summary>¸ù¾ÝÊäÈë»ñÈ¡½¨Òé´Ê</summary>
public List<String> GetSuggestions(String input)
{
if (input.IsNullOrEmpty()) return new List<String>();
var upperInput = input.ToUpper();
return _words
.Where(w =>
{
// Ö§³ÖÊ××ÖĸƥÅä
var first = PinYin.GetFirst(w);
if (first.StartsWith(upperInput, StringComparison.OrdinalIgnoreCase))
return true;
// Ö§³ÖȫƴƥÅä
var full = PinYin.Get(w);
return full.StartsWith(upperInput, StringComparison.OrdinalIgnoreCase);
})
.Take(10)
.ToList();
}
}
// ʹÓÃʾÀý
var words = new List<String> { "ÐÂÉúÃü", "ÐÂÄêºÃ", "ÐÂÊÖÈëÃÅ", "ÉúÈÕ¿ìÀÖ" };
var suggester = new InputSuggestion(words);
suggester.GetSuggestions("XS"); // ["ÐÂÉúÃü", "ÐÂÊÖÈëÃÅ"]
suggester.GetSuggestions("Xin"); // ["ÐÂÉúÃü", "ÐÂÄêºÃ", "ÐÂÊÖÈëÃÅ"]
```
### 5. Êý¾Ý¿â´æ´¢ÓÅ»¯
```csharp
public class User
{
public Int32 Id { get; set; }
public String Name { get; set; }
/// <summary>ÐÕÃûÆ´Òô£¨ÓÃÓÚËÑË÷£©</summary>
public String NamePinyin { get; set; }
/// <summary>ÐÕÃûÊ××Öĸ£¨ÓÃÓÚË÷Òý£©</summary>
public String NameFirst { get; set; }
/// <summary>±£´æÇ°×Ô¶¯Éú³ÉÆ´Òô×Ö¶Î</summary>
public void BeforeSave()
{
NamePinyin = PinYin.Get(Name);
NameFirst = PinYin.GetFirst(Name);
}
}
// Êý¾Ý¿â²éѯʱ¿ÉÀûÓÃÆ´Òô×ֶμÓËÙËÑË÷
// SELECT * FROM Users WHERE NameFirst LIKE 'ZS%'
// SELECT * FROM Users WHERE NamePinyin LIKE 'Zhang%'
```
## ¼¼Êõϸ½Ú
### ±àÂë»ù´¡
PinYin Àà»ùÓÚ GB2312 ±àÂëʵÏÖ£º
1. **Ò»¼¶ºº×Ö**£º¹² 3755 ¸ö£¬°´Æ´Òô˳ÐòÅÅÁÐ
2. **¶þ¼¶ºº×Ö**£º¹² 3008 ¸ö£¬°´²¿Êױʻ˳ÐòÅÅÁÐ
3. **ÌØÊ⺺×Ö**£º³¬³ö GB2312 ·¶Î§µÄ³£Óúº×Öµ¥¶À´¦Àí
### Ëã·¨ÔÀí
```
×Ö·û ¡ú GB2312±àÂë ¡ú ÇøÎ»Âë ¡ú Æ´ÒôÓ³Éä
```
1. ½«ºº×Öת»»Îª GB2312 ×Ö½Ú
2. ¼ÆËãÇøÎ»Â루Á½×Ö½ÚÏà³ËÔÙ¼õÆ«ÒÆ£©
3. Ò»¼¶ºº×Öͨ¹ýÇø¼äÓ³Éä¿ìËÙ¶¨Î»Æ´Òô
4. ¶þ¼¶ºº×Öͨ¹ýÊý×é²éÕÒ»ñȡƴÒô
### ÐÔÄÜÌØµã
- **ÎÞ×Öµä¼ÓÔØ**£ºËã·¨Ö±½Ó¼ÆË㣬Æô¶¯¼´¿ÉÓÃ
- **O(1) ¸´ÔÓ¶È**£ºÒ»¼¶ºº×Öͨ¹ý·Ö¿éËã·¨¿ìËÙ¶¨Î»
- **ÄÚ´æÕ¼ÓÃС**£º½ö´æ´¢Æ´Òô¶ÔÕÕÊý×é
## ÏÞÖÆËµÃ÷
### ¶àÒô×Ö
Ŀǰ²»Ö§³Ö¶àÒô×ÖÉÏÏÂÎÄÅжϣ¬¶àÒô×ÖÈ¡³£ÓöÁÒô£º
```csharp
PinYin.Get('ÖØ') // "Zhong"£¨¶ø·Ç "Chong"£©
PinYin.Get("ÖØÇì") // "ChongQing"£¨ÌØÊâ´¦Àí£©
PinYin.Get("ÖØÒª") // "ZhongYao"£¨°´³£ÓöÁÒô£©
```
### ÉúƧ×Ö
³¬³ö GB2312 ·¶Î§µÄÉúƧ×Ö¿ÉÄÜÎÞ·¨×ª»»£º
```csharp
PinYin.Get('?') // "?"£¨ÎÞ·¨Ê¶±ð£¬ÔÑù·µ»Ø£©
```
### ·±Ìå×Ö
²»Ö§³Ö·±Ìå×Öת»»£¬ÐèÒªÏÈת¼òÌ壺
```csharp
PinYin.Get('‡ø') // "‡ø"£¨ÎÞ·¨Ê¶±ð£©
PinYin.Get('¹ú') // "Guo"£¨¼òÌåÕý³££©
```
## ×î¼Ñʵ¼ù
### 1. Ô¤´¦ÀíÆ´Òô×Ö¶Î
```csharp
// ÍÆ¼ö£ºÈë¿âʱԤÏȼÆËãÆ´Òô
user.NamePinyin = PinYin.Get(user.Name);
user.NameFirst = PinYin.GetFirst(user.Name);
db.Save(user);
// ²»ÍƼö£ºÃ¿´Î²éѯʱʵʱ¼ÆËã
var users = db.Users.Where(u => PinYin.GetFirst(u.Name) == "ZS");
```
### 2. ×éºÏËÑË÷²ßÂÔ
```csharp
// ÍÆ¼ö£ºÍ¬Ê±Ö§³ÖÔÎÄºÍÆ´ÒôËÑË÷
public List<User> Search(String keyword)
{
return users.Where(u =>
u.Name.Contains(keyword) ||
u.NamePinyin.Contains(keyword.ToUpper()) ||
u.NameFirst.Contains(keyword.ToUpper())
).ToList();
}
```
### 3. »º´æ³£ÓÃת»»
```csharp
// ¶ÔÓÚ¸ßÆµ×ª»»µÄ´Ê»ã£¬¿É¿¼ÂÇ»º´æ
private static readonly ConcurrentDictionary<String, String> _cache = new();
public static String GetCached(String str)
{
return _cache.GetOrAdd(str, s => PinYin.Get(s));
}
```
## Ïà¹ØÁ´½Ó
- [×Ö·û´®À©Õ¹ StringHelper](/NewLife/X/Blob/dev/Doc/string_helper-×Ö·û´®À©Õ¹StringHelper.md)
- [ÀàÐÍת»» Utility](/NewLife/X/Blob/dev/Doc/utility-ÀàÐÍת»»Utility.md)
|