Форматирование буквенно-цифровой строки - PullRequest
7 голосов
/ 18 февраля 2010

У меня есть строка с 16 алфавитно-цифровыми символами, например, F4194E7CC775F003.Я хотел бы отформатировать его как F419-4E7C-C775-F003.

Я пытался использовать

string.Format("{0:####-####-####-####}","F4194E7CC775F003");

, но это не работает, поскольку это не числовое значение.

Итак, я придумал следующее:

public class DashFormatter : IFormatProvider, ICustomFormatter
{
  public object GetFormat(Type formatType)
  {
    return this;
  }

  public string Format(string format, object arg, IFormatProvider formatProvider)
  {
    char[] chars = arg.ToString().ToCharArray();
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < chars.Length; i++)
    {
      if (i > 0 && i % 4 == 0)
      {
        sb.Append('-');
      }

      sb.Append(chars[i]);
    }

    return sb.ToString();
  }
}

и с помощью

string.Format(new DashFormatter(), "{0}", "F4194E7CC775F003");

я смог решить проблему, однако я надеялся, что есть лучшее / более простоеспособ сделать это?Возможно, какая-то магия LINQ?

Спасибо.

Ответы [ 7 ]

8 голосов
/ 18 февраля 2010

Вы можете сделать это в одну строку без Linq:

        StringBuilder  splitMe = new StringBuilder("F4194E7CC775F003");
        string joined = splitMe.Insert(12, "-").Insert(8, "-").Insert(4, "-").ToString();
2 голосов
/ 18 февраля 2010

Вы могли бы сделать это с помощью регулярного выражения, хотя я не знаю, какую производительность по сравнению с другими методами.

string formattedString = Regex.Replace(yourString, "(\\S{4})\\B", "$1-");

Вы также можете поместить это в метод расширения для строки, если хотите:

yourString.ToDashedFormat();
1 голос
/ 18 февраля 2010

На основании Ответ Карры Я сделал этот маленький вспомогательный метод:

private static string ToDelimitedString(string input, int position, string delimiter)
{
  StringBuilder sb = new StringBuilder(input);

  int x = input.Length / position;

  while (--x > 0)
  {
    sb = sb.Insert(x * position, delimiter);
  }

  return sb.ToString();
}

Вы можете использовать его так:

string result = ToDelimitedString("F4194E7CC775F003", 4, "-");

И контрольный пример:

[Test]
public void ReturnsDelimitedString()
{
  string input = "F4194E7CC775F003";

  string actual = ToDelimitedString(input, 4, "-");

  Assert.AreEqual("F419-4E7C-C775-F003", actual);
}
1 голос
/ 18 февраля 2010

Если хотите, linq:

var formatted = string.Join("-", Enumerable.Range(0,4).Select(i=>s.Substring(i*4,4)).ToArray());

И если вы хотите, чтобы это было эффективно:

var sb = new StringBuilder(19);
sb.Append(s,0,4);
for(var i = 1; i < 4; i++ )
{
 sb.Append('-');
 sb.Append(s,i*4, 4);
}
return sb.ToString();

Я не тестировал этот тест, но я думаю, что он будет быстрее, чем StringBuilder.Insert, потому что он не перемещает остальную часть строки много раз, он просто записывает 4 символа. Кроме того, он не будет перераспределять нижележащую строку, потому что вначале он был предварительно выделен до 19 символов.

0 голосов
/ 24 апреля 2019

Только 9 лет спустя, незначительное отклонение от ответа Карры. Это дает примерно 2,5-кратное улучшение скорости на основе моих тестов (измените все "-" на "-"):

        StringBuilder initial = new StringBuilder("F4194E7CC775F003");
        return initial.Insert(12, '-').Insert(8, '-').Insert(4, '-').ToString();
0 голосов
/ 18 февраля 2010

Самое простое решение, которое я могу придумать, это

        var text = "F4194E7CC775F003";
        var formattedText = string.Format(
            "{0}-{1}-{2}-{3}",
            text.Substring(0, 4),
            text.Substring(4, 4),
            text.Substring(8, 4),
            text.Substring(12, 4));
0 голосов
/ 18 февраля 2010
 char[] chars = "F4194E7CC775F003".ToCharArray();
            var str = string.Format("{0}-{1}-{2}-{3}"
                                  , new string(chars.Take(4).ToArray())
                                  , new string(chars.Skip(4).Take(4).ToArray())
                                  , new string(chars.Skip(8).Take(4).ToArray())
                                  , new string(chars.Skip(12).Take(4).ToArray())  
                );
...