private static (DigitType DigitType, double Number) ToNumber(string Text) { if (Regex.IsMatch(Text, $"^[{Kanji}]")) { return(DigitType.Kanji, Kansuji.Convert(Text)); } else if (Regex.IsMatch(Text, $"^[{HalfWidth}]")) { return(DigitType.HalfWidth, double.Parse(Strings.StrConv(Text, VbStrConv.Narrow))); } else if (Regex.IsMatch(Text, $"^[{FullWidth}]")) { return(DigitType.FullWidth, double.Parse(Strings.StrConv(Text, VbStrConv.Narrow))); } else if (Regex.IsMatch(Text, Other)) { return(DigitType.Other, 0.5); } else { return(DigitType.NotDigit, 0); } }
/// <summary> /// 調整比率適用 /// </summary> /// <param name="source">元文字列</param> /// <param name="adjustment">調整比率</param> /// <returns>調整比率適用後文字列</returns> public static string Apply(this string input, double adjustment) { try { if (adjustment == 1) { return(input); } var target = input; // 分量として成り立つかどうかの正規表現 var digitRegex = new Regex($"^([{Kanji}]+|[{HalfWidth}{FullWidth}{Symbol}]+|{Other})"); // もとの文字列を単語単位で分割した単語リスト var words = new List <Word>(); // 分量になりそうにない文字列を一時的に入れておく変数 var temporary = ""; // 1文字ずつ処理して、全て処理し終わるまでループする while (target.Length != 0) { // 先頭から始まる1文字以上の文字列が分量になり得るかどうか if (digitRegex.IsMatch(target)) { // 先頭の文字が分量になりそうな場合、今まで溜め込んでいた一時変数の文字列を単語リストに追加する if (temporary.Length != 0) { words.Add(new Word(temporary, 0, DigitType.NotDigit)); temporary = ""; } // 分量調整対象として単語リストに追加 words.Add(new Word(digitRegex.Match(target).Result("$1"), 0, DigitType.Unknown)); target = digitRegex.Replace(target, ""); } else { // 分量になりそうなもの以外は一時変数に入れておき、あとでまとめて単語リストに追加する var firstChar = target[0]; temporary += firstChar; target = target.Remove(0, 1); } } if (temporary.Length != 0) { words.Add(new Word(temporary, 0, DigitType.NotDigit)); } return(string.Join("", words.Select(x => { if (x.DigitType == DigitType.Unknown) { if (x.Text.Where(c => c == '/' || c == '/').Count() == 1) { var splitted = x.Text.Split('/', '/'); var num0 = ToNumber(splitted[0]); var num1 = ToNumber(splitted[1]); x.DigitType = num0.DigitType; x.Num = num0.Number / num1.Number; } else { (x.DigitType, x.Num) = ToNumber(x.Text); } } if (x.DigitType != DigitType.NotDigit) { x.Num *= adjustment; } switch (x.DigitType) { case DigitType.FullWidth: x.Text = Strings.StrConv(x.Num.ToString(), VbStrConv.Wide); break; case DigitType.HalfWidth: x.Text = x.Num.ToString(); break; case DigitType.Other: x.Text = x.Num.ToString() + (x.Text[1] != '分' ? x.Text[1].ToString() : ""); break; case DigitType.Kanji: x.Text = Kansuji.Convert((long)x.Num); break; default: break; } return x.Text; }))); } catch (Exception) { return(input); } }