2014-01-13 5 views
0

Я работаю на странице бритвы, где мне нужно отбросить ряд пользовательских полей из таблиц переменных-атрибутов. Моя цель - заменить определенное сопряжение символов ('{}') на htmlstring. Чтобы упростить, однако, скажем, я хотел заменить его инкрементным числом.Заменить строку на петлю

Это псевдокод для того, что я ищу.

string s = "This sample will count: {}, {}, {}." 
int i = 0; 
while(*string not finished*)//? 
{ 
    i ++; 
    s.Replace("{}", i); 
} 

Выход:

"This sample will count 1, 2, 3." 

Это то, что мне нужно использовать регулярное выражение на? Любые другие мысли?

EDIT

Я должен уточнить: Я не знаю, сколько '{}' s до времени выполнения. Числа могут быть метание людей прочь, я любя собираюсь сделать что-то более похожее на:

s.replace("{}", stringArray[i]); 
+0

Строки неизменны в '.NET'. Может только преобразовываться из одной строки в другую. – ja72

+0

@ ja72 Да, я знаю, но даже если бы я поменял его на StringBuilder, это то, что заменит, вероятно, за кулисами, мой вопрос остается в силе, я думаю. Цель состоит не в том, чтобы рассчитывать, а в том, чтобы заменить каждую подстроку, соответствующую шаблону, на ** другую ** подстроку. В моем фактическом примере источник, вероятно, будет строками из массива или списка. Если бы я сделал s.replace (1) Тогда выход был бы «Этот образец будет считать 1, 1, 1» – Seth

+1

Итак, вы пытаетесь реплицировать 'string.Format()', но без цифр внутри фигурных скобок? – Magus

ответ

2

Вы можете использовать регулярное выражение match evaluator следующим образом:

var re = new Regex(@"\{\}"); 

string s = "This sample will count: {}, {}, {}."; 

string[] replacementStrings = new string[]{"r1", "r2", "r3"}; 

int i = 0; 

string n = re.Replace(s, m => 
    { 
     return replacementStrings[i++]; 
    }); 

Console.WriteLine(n); // outputs: This sample will count: r1, r2, r3. 
+0

Спасибо, хотя у меня не будет возможности жестко закодировать количество заменяющих строк. – Seth

+0

Просьба уточнить. Вышеупомянутое решение основано на вашем EDIT относительно s.replace ("{}", stringArray [i]); – wdosanjos

+0

В вашем коде учитываются, в частности, три пары кронштейнов. В противном случае он функционирует достаточно хорошо. – Seth

0

Вы могли бы сделать это с простым старой строкой manupulation:

string s = "This sample will count: {}, {}, {}."; 
string[] stringArray = new[] { "1", "2", "3" }; 
int i = 0, c = s.IndexOf("{}"); 
while(c >= 0) 
{ 
    s = s.Remove(c) + stringArray[i++] + s.Substring(c + 2); 
    c = s.IndexOf("{}"); 
} 
// s == "This sample will count: 1, 2, 3." 

Или с помощью регулярных выражений:

string s = "This sample will count: {}, {}, {}."; 
string[] stringArray = new[] { "1", "2", "3" }; 
int i = 0; 
s = Regex.Replace(s, "{}", m => stringArray[i++]); 
// s == "This sample will count: 1, 2, 3." 

Или с помощью Linq:

string s = "This sample will count: {}, {}, {}."; 
string[] stringArray = new[] { "1", "2", "3" }; 
s = String.Join("", s.Split(new[]{ "{}" }, StringSplitOptions.None) 
        .Select((x, i) => i < stringArray.Length ? x + stringArray[i] : x)); 
// s == "This sample will count: 1, 2, 3." 
+1

Эти примеры будут иметь низкую производительность из-за количества создаваемых строк. – Haney

+1

@DavidHaney Плохая производительность по сравнению с чем? Есть ли у вас доказательства того, что эта «потеря» производительности будет значимой? – BartoszKP

+0

Да, строки будут созданы, и, следовательно, необходимо собрать мусор. Вы создадите намного больше Gen 0 или 1, возможно, 2 события GC, что замедлит ваше приложение. 'StringBuilder' существует SOLELY, чтобы обойти накладные расходы на создание экземпляров строк в качестве побочных продуктов операций, которые многократно манипулируют ими. – Haney

-1

Другое решение:

string fmt = "This sample will count: {0}, {1}, {2}."; 
int[] values = new int[3]; 
for (int i = 0; i < values.Length; i++) { 
    values[i] = i; 
} 
string s = string.Format(fmt, values[0], values[1], values[2]); 

Это берет другой логический подход к тому, что вы выложили, и может или не может работать с вашим проектом.

+1

К сожалению, это не очень хорошо из-за двух ограничений. Во-первых, я не знаю, сколько скобок у меня будет во время компиляции, а во-вторых, у меня не будет цифр, необходимых для string.format. Спасибо, хотя – Seth

+0

Это на самом деле даже не ответ, это просто более ограниченный способ вызвать 'string.Format()', который уже принимает массив. – Magus

+0

@Magus: Я не вижу ответа, который вы внесли в эту тему. – jp2code

3

Простой пример с использованием Split для тонирования вашей входной строки;

string s = "This sample will count: {}, {}, {}."; 
string[] tokens = s.Split(new[] { "{}"}, StringSplitOptions.None); 
StringBuilder sb = new StringBuilder(); 

int counter = 1; 
for (int i = 0; i < tokens.Length; i++) 
{ 
    sb.Append(tokens[i]); 
    if (i < tokens.Length - 1) 
     sb.Append(counter++); 
} 

Console.WriteLine(sb.ToString()); 

Решает ваш опубликованный пример, но я предполагаю, что ваше реальное требование будет более сложным.

+0

Это исключает последний токен. (в этом случае '.' в конце) –

+0

Исправлено (но не проверено) –

+0

Прохладный, что работает (с данным примером) –

1

Если производительность важна для вас, пройдите строку вручную и записать его содержимое к StringBuilder (для предотвращения тонн струны экземпляров произведений в то время как конкатенации и замены строк), а затем найти и заменить экземпляры {}. string.IndexOf было бы полезно использовать для этого. После того, как вы закончите, кэшировать результат и вывода строки построитель через StringBuilder.ToString()

Смежные вопросы