#c# #.net #string
#c# #.net #строка
Вопрос:
Я хотел бы изменить исходную строку, которая выглядит как
"one.two.three"
и перенесите ее в строку с косыми чертами, чтобы использовать ее как строку папки, которая имеет следующую структуру:
"oneone.twoone.two.three"
Знаете ли вы более элегантные способы реализовать это, чем мое решение ниже? Я не очень доволен своими циклами for.
var folder = "one.two.three";
var folderParts = folder.Split('.');
var newFolder = new StringBuilder();
for (int i = 0; i < folderParts.Length; i )
{
for (int j = 0; j < i; j )
{
if (j == 0)
{
newFolder.Append("\");
}
newFolder.Append($"{folderParts[j]}.");
}
newFolder.Append(folderParts[i]);
}
Комментарии:
1. Должен быть способ сделать это с помощью Aggregate, но я не могу точно указать на это.
Ответ №1:
Вы можете сделать это довольно кратко с помощью Regex
var newFolder = Regex.Replace(folder, @".", @"$`.");
Это соответствует каждому периоду. Каждый раз, когда он находит точку, он вставляет обратную косую черту, а затем всю входную строку перед совпадением ( $`
). Мы должны снова добавить точку в конце.
Итак, шаги (< и > указывают текст, вставленный заменой на этом шаге):
- Совпадение в 1-м периоде.
one<one>.two.three
- Совпадение во 2-м периоде.
oneone.two<one.two>.three
- Результат:
oneone.twoone.two.three
Для получения бонусных баллов используйте Path.DirectorySeparatorChar
за кроссплатформенную корректность.
var newFolder = Regex.Replace(folder, @".", $"{Path.DirectorySeparatorChar}$`.")
Вот еще один способ linqy:
var a = "";
var newFolder = Path.Combine(folder.Split('.')
.Select(x => a = (a == "" ? "" : ".") x).ToArray());
Комментарии:
1. Отлично! Просто замените, чтобы получить результат
2. Это, конечно, самое короткое решение, но его довольно сложно прочитать, если вы не любитель регулярных выражений. Спасибо за подробное объяснение! 🙂
3. Также благодарю вас за подсказку относительно кроссплатформенной совместимости.
4. @Christoph согласился. Я сказал, что это кратко, а не то, что это обязательно читаемо! Честно говоря, я бы написал комментарий против любого из этих решений, в котором говорилось бы, что оно сделало. Вы можете добавить несколько дополнительных строк комментариев к этой, объясняющих, как это работает, прежде чем она станет такой же длинной, как следующий самый краткий ответ.
Ответ №2:
Вы можете попробовать Linq:
string folder = "one.two.three";
string[] parts = folder.Split('.');
string result = Path.Combine(Enumerable
.Range(1, parts.Length)
.Select(i => string.Join(".", parts.Take(i)))
.ToArray());
Console.Write(newFolder);
Результат:
oneone.twoone.two.three
Комментарии:
1. Возможно, использовать
Path.Combine
поверх этой первойstring.Join
для кроссплатформенности?2. @canton7: Спасибо!
Path.Combine
намного лучше в контексте
Ответ №3:
Вы можете двигаться вперед — только в одном цикле, подобном этому:
var folder = "one.two.three";
var newFolder = new StringBuilder();
int index = -1;
while (index 1 < folder.Length) {
index = folder.IndexOf('.', index 1);
if (index < 0) {
newFolder.Append(folder);
break;
}
else {
newFolder.Append(folder, 0, index);
newFolder.Append(Path.DirectorySeparatorChar);
}
}
Вы можете попробовать это здесь.
Ответ №4:
Вместо того, чтобы сначала разбивать строку, я нахожу более элегантным начать с того, что у вас есть, и сократить его:
var folder = "one.two.three";
var newFolder = string.Empty;
for (var f = folder; f.Any(); f = f.Remove(Math.Max(f.LastIndexOf('.'), 0)))
newFolder = Path.Combine(f, newFolder);
Console.WriteLine(newFolder);
Вывод:
oneone.twoone.two.three