2013-11-07 2 views
1

Я следующую задачу: Когда я используюLinq - Совокупные строки с кавычками

var newItems = {"one", "two"} 
var a = newItems.Aggregate((current, c) => current + ", \"" + c + "\""); 

я получаю: "один, два"

Вместо ожидалось: "\" один \ "\" два \ ""

Кто может объяснить мне, почему это происходит?

+4

На самом деле ваш код возвращает ' "один \" два \ ""' ... в любом случае, это правильное положение, где вы должны использовать 'string.join ("", newItems. Выберите (x => "\" "+ x +" \ "")) ' – digEmAll

+1

@digEmВсе прочитайте это как ответ. –

+1

@digEmAll Опубликуйте свой комментарий, и я считаю его правильным! – BotanMan

ответ

2

Вы должны сделать это таким образом

string output=String.Join(",",newItems.Select(x=>"\""+x+"\"")); 

Альтернативное решение

StringBuilder sb=new StringBuilder(); 
newItems.ToList() 
     .ForEach(x=>sb.Append(","+String.Format("\"{0}\"",x))); 
string output=sb.ToString().Trim(','); 
+0

@AkashKava Это совпадение. Хотя он должен был разместить его как ответ – Anirudha

+1

Совпадение с разницей во времени в 4 минуты? –

+0

На самом деле этот ответ лучше, чем совокупности, предоставленные здесь. Но можете ли вы добавить объяснения, почему это лучше? –

0

Вы должны обернуть оба current и c вокруг цитаты:

var a = newItems.Aggregate((current, c) => "\"" + current + "\", \"" + c + "\""); 

Этот код возвращает ожидаемый результат.

+2

Для двух входов да, но это даст слишком много котировок для трех или более входов. – Rawling

+0

Спасибо, я думал, что совокупная работа с String.Empty как накапливает значение, так хорошо и спасибо, теперь я понимаю, что я ошибся! – BotanMan

0

По умолчанию Aggregate берет свое первое значение и использует его как свое семя, поэтому он примет one и добавит , "two" к нему. Что вам нужно сделать, это указать пустое семя и сделать что-то особенное, когда (т.е. не ставить запятую), вы получите пустой семя:

var newItems = new[] {"one", "two"}; 
var a = "The following items will be created: " + 
     newItems.Aggregate("", (current, c) => 
       (current == "" ? "" : current + ", ") + "\"" + c + "\""); 
0

Вы забыли возможность размещения предыдущий и текущий элемент в кавычках:

var newItems = new[]{"one", "two"}; 
var strout = '"' + newItems.Aggregate((a, b) => a + "\", \"" + b)+ '"'; 

Результат:

"one", "two" 
+2

Для двух входов да, но это даст слишком много котировок для трех или более входов. – Rawling

+1

@ Rawling Мой плохой. Благодарю. –

1

Использование совокупности со строками не очень хорошая идея, потому что она будет создавать новую строку в памяти на каждой итерации. Я предлагаю вам использовать String.Join (внутренне использует StringBuilder) или непосредственно использовать StringBuilder в качестве аккумулятора:

var a = newItems.Aggregate(
      new StringBuilder(), // avoid intermediate strings creation 
      (sb, s) => sb.AppendFormat("{0}\"{1}\"", sb.Length > 0 ? "," : "", s), 
      sb => sb.ToString()); 

Таким образом, вы не просто хотите конкатенации строк, но и Присоединяйся к ним с какой-то символ, то String.Join это естественный способ сделать это ,

+1

A. Исправить в селекторе результатов, чтобы удалить завершающий символ ',' делает это * немного * менее уродливым. Я бы по-прежнему использовал String.Join/Format для получения более читаемого кода, если только производительность действительно не повредит. Или скрыть всю конструкцию в методе расширения, hmmm ... –

+0

@PanagiotisKanavos согласен, удалите выглядит лучше, и соглашайтесь снова, я бы пошел с Join. +1 от меня –

1

Следует избегать использования конкатенации строк, где это возможно. Строки неизменяемы, поэтому конкатенация строк создает новые временные строки, которые впоследствии нужно собрать мусором. Это может быть серьезной проблемой, если вы регулярно выполняете множество операций с строками.

Вы можете использовать String.Join и String.Forma т для создания строки с разделителями из списка значений, как это:

var newItems = new [] {"one", "two"}; 
var a = String.Join(", ",newItems.Select(c => String.Format("\"{0}\"",c))); 

Это создает временные строки, хотя они намного меньше, чем раньше.

Вы также можете использовать StringBuilder и агрегированный для создания одной строки и избежать каких-либо временных строк, хотя код выглядит немного уродливый:

var builder = new StringBuilder(); 
var b1 = (newItems.Aggregate(builder, 
      (bld, c) => bld.AppendFormat("\"{0}\",", c), 
      bld => bld.Remove(bld.Length - 1, 1)) 
     ).ToString(); 

или даже

var b2 = newItems.Aggregate(builder2, 
     (bld, c) => bld.AppendFormat("\"{0}\",", c), 
     bld => bld.Remove(bld.Length - 1, 1).ToString()); 

Если вам нужно чтобы использовать такой код во многих местах, было бы лучше скрыть всю конструкцию в методе расширения:

public static string JoinFormat<T>(this IEnumerable<T> items,string format) 
{ 
    var builder = new StringBuilder(); 
    var result = (items.Aggregate(builder, 
      (bld, c) => bld.AppendFormat(format, c), 
      bld => bld.Remove(bld.Length - 1, 1)) 
     ).ToString(); 
    return result; 
} 

и написать:

var a=newItems.JoinFormat("\"{0}\""); 
Смежные вопросы