두 개의 ASCII 문자를 '해당'한 문자 확장 된 ASCII 표현으로 변환
-
18-09-2019 - |
문제
문제 : 외부 시스템에서 두 개의 고정 너비 문자열이 있습니다. 첫 번째에는 기본 문자 (AZ : AZ)가 포함되어 있으며, 두 번째 (5 월)에는 실제 문자를 만들기 위해 첫 번째 문자열에 추가되는 디아크리닉이 포함되어 있습니다.
string asciibase = "Dutch has funny chars: a,e,u";
string diacrits = " ' \" \"";
//no clue what to do
string result = "Dutch has funny chars: á,ë,ü";
나는 대규모 검색을 작성하고 모든 캐릭터 + 다른 Diacritics를 대체 할 수 있었지만 좀 더 우아한 것을 기대하고있었습니다.
누군가 이것을 고치는 방법에 대한 단서가 있습니까? 문자열을 사용하여 소수점 값을 계산하여 시도했지만 결과는 없었습니다. 또한 Google은 실제로 무언가로 나타나지 않았습니다.
해결책
조회 테이블을 사용하는 것 외에는 쉬운 솔루션을 찾을 수 없습니다.
public void TestMethod1()
{
string asciibase = "Dutch has funny chars: a,e,u";
string diacrits = " ' \" \"";
var merged = DiacritMerger.Merge(asciibase, diacrits);
}
편집 : @jonb 및 @oliver의 답변에서 제안한 후 단순화 된 코드
public class DiacritMerger
{
static readonly Dictionary<char, char> _lookup = new Dictionary<char, char>
{
{'\'', '\u0301'},
{'"', '\u0308'}
};
public static string Merge(string asciiBase, string diacrits)
{
var combined = asciiBase.Zip(diacrits, (ascii, diacrit) => DiacritVersion(diacrit, ascii));
return new string(combined.ToArray());
}
private static char DiacritVersion(char diacrit, char character)
{
char combine;
return _lookup.TryGetValue(diacrit, out combine) ? new string(new [] {character, combine}).Normalize()[0] : character;
}
}
다른 팁
Diacritical Marks 범위를 결합한 유니 코드에서 적절한 유니 코드 값으로 디아크리닉을 변환하십시오.
http://www.unicode.org/charts/pdf/u0300.pdf
그런 다음 char와 그 diacritic을 e-acute, u+0065 = "e"및 u+0301 = 급성에 대해 char와 diacritic을 두드리십시오.
String s = "\u0065\u0301";
그 다음에:
string normalisedString = s.Normalize();
둘을 새 문자열로 결합합니다.
문제는 지정된 직경이 명시 적으로 구문 분석되어야한다는 것입니다. 이중 점이 단독으로 존재하지 않으므로이 경우에는 이중 인용문이 사용됩니다. 따라서 문제를 해결하려면 다른 기회가없고 필요한 각 사례를 구현할 수 없습니다.
여기에 단서를 얻는 출발점이 있습니다 ...
public SomeFunction()
{
string asciiChars = "Dutch has funny chars: a,e,u";
string diacrits = " ' \" \"";
var combinedChars = asciiChars.Zip(diacrits, (ascii, diacrit) =>
{
return CombineChars(ascii, diacrit);
});
var Result = new String(combinedChars.ToArray());
}
private char CombineChars(char ascii, char diacrit)
{
switch (diacrit)
{
case '"':
return AddDoublePoints(ascii);
case '\'':
return AddAccent(ascii);
default:
return ascii;
}
}
private char AddDoublePoints(char ascii)
{
switch (ascii)
{
case 'a':
return 'ä';
case 'o':
return 'ö';
case 'u':
return 'ü';
default:
return ascii;
}
}
private char AddAccent(char ascii)
{
switch (ascii)
{
case 'a':
return 'á';
case 'o':
return 'ó';
default:
return ascii;
}
}
}
ienumerable.zip은 이미 있습니다 .NET 4에서 구현되었습니다, 그러나 3.5로 얻으려면이 코드가 필요합니다 (Eric Lippert에서 가져 왔습니다):
public static class IEnumerableExtension
{
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>
(this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (resultSelector == null) throw new ArgumentNullException("resultSelector");
return ZipIterator(first, second, resultSelector);
}
private static IEnumerable<TResult> ZipIterator<TFirst, TSecond, TResult>
(IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
using (IEnumerator<TFirst> e1 = first.GetEnumerator())
using (IEnumerator<TSecond> e2 = second.GetEnumerator())
while (e1.MoveNext() && e2.MoveNext())
yield return resultSelector(e1.Current, e2.Current);
}
}
C#또는 표준 라이브러리를 모르지만 하나의 대안 적 접근 방식은 기존 HTML/SGML/XML 문자 엔티티 파서/렌더러와 같은 것을 사용하거나 실제로 브라우저에 제시하려는 경우 아무것도 아님!
의사 코드 :
for(i=0; i < strlen(either_string); i++) {
if isspace(diacrits[i]) {
output(asciibase[i]);
}else{
output("&");
output(asciibase[i]);
switch (diacrits[i]) {
case '"' : output "uml"; break;
case '^' : output "circ"; break;
case '~' : output "tilde"; break;
case 'o' : output "ring"; break;
... and so on for each "code" in the diacrits modifier
... (for acute, grave, cedil, lig, ...)
}
output(";");
}
}
따라서, A + o
-> Å
, u + "
-> ü
등등.
그런 다음 HTML 엔티티를 구문 분석 할 수 있다면 집에 무료로 있어야하며 숯 사이에 휴대용이 있어야합니다!