string.Join throws OutOfMemory Exception - c#

I have a list of strings and I want to join them with " "(space) between them, so I use the string.Join method:
foreach (var line in lines)
{
var strings = lines.Where(l => l.Code == line.Code).Select(l => l.Data);
var original = string.Join(" ", strings);
}
Data looks something like this: "123456789, 987654321, 32132, 7873892 ..."
But I get an OutOfMemoryException. Why? each string is approximatly 100-150 characters and there are 5-10 strings in the list.
Is there a better way then the string.Join?

Try this (and let us know if you get the same error):
lines.GroupBy(l => l.Code).Select(l => string.Join(" ", l.Select (x => x.Data)));

foreach (var line in lines.GroupBy(p=>p.Code))
{
var original = string.Join(" ", line.Select(p=>p.Data));
}

The StringBuild() class can join strings and isn't immutable.
Here's an MSDN article talking about immutable string vs how StringBuilder works.
http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx

Related

How to turn array into quote and comma delimited string for sql?

I have a list I want to pass into SQL but they must be single quote and comma delimited.
So List = a b c
But I need a string = 'a','b','c'
How can I accomplish this in a concise manner?
Something like this I think but can't see within LINQ how to add to beginning and end:
String.Join(",", arr.Select(p => p.ToString()).ToArray())
Maybe something along the lines of:
String.Join(",", arr.Select(p=> "'" + p.ToString() + "'").ToArray());
// or is p already a string
String.Join(",", arr.Select(p => "'" + p + "'").ToArray());
You can do this:
String.Join(",", arr.Select(p => $"'{p.ToString()}'").ToArray());
And that will put the ' on either side of p.ToString() for each element.
Use an ORM that supports the following construction:
string[] items = GetItems();
var query = db.Rows.Where(row => items.Contains(row.ColumnName));
This way, you do not open yourself to sql injection by constructing strings to hand to the database yourself.
You should also be careful if your source data contains "'" in which case you need to escape the "'". Try this:
var arr = new [] { "a'c", "b" };
var output = String.Join(",", arr.Select(p => $"'{p.Replace("'", "''")}'"));
That gives "'a''c','b'".

Is there a one-liner to get specific parts of this string?

I'm having a string like "a.b.c.d.e".
If I want to get an array like "a.b.c.d.e", "b.c.d.e", "c.d.e", "d.e", "e" in C#. What's the simplest approach?
Something like this will do:
var stringParts = input.Split('.');
var result = Enumerable.Range(0, stringParts.Length)
.Select(i => string.Join(".", stringParts.Skip(i)));
But like I said in my comment, please show the code you came up with and why you want to make it a one-liner, which usually doesn't serve any benefit. This isn't codegolf.
If you really do it with one statement, you can try this:
var str = "a.b.c.d.e";
var parts = str.Split('.')
.Select((x,idx) => new { idx })
.Select(p => string.Join(".",
str.Split('.').Skip(p.idx))).ToList();
This could be more efficient if you use Split first:
var parts = str.Split('.');
var result = parts
.Select((x,idx) => new { idx })
.Select(p => string.Join(".",
parts.Skip(p.idx))).ToList();
You can also do it without creating anonymous type(s), just create an int variable:
int i = 0;
var result = parts
.Select(p => string.Join(".", parts.Skip(i++)))
.ToList();
This is fairly neat:
var text = "a.b.c.d.e";
var results =
text
.Split('.')
.Reverse()
.Scan("", (a, x) => x + "." + a)
.Select(x => x.TrimEnd('.'))
.Reverse();
You do need to add the Microsoft Reactive Extensions Team's "Interactive Extensions" to get the Scan operator. Use NuGet and look for "Ix-Main".
I actually kind of like this question, not necessarily production but a bit of brain-bendy fun:
"a.b.c.d.e".Split('.').Reverse()
.Aggregate(Enumerable.Empty<string>(), (acc, c) =>
acc.Concat(new [] { c+(acc.LastOrDefault()??"") })
).Reverse()
Dotnetfiddle
What this does is move through each character in the split array and build up a new array by prepending the last value in the array with the current character. It's a fairly common functional programming technique.
Well, this is how I might write it.. I know, not "one line", but if you're gonna use (and I do recommend) a method anyway..
IEnumerable<string> AllComponentPartsForward (string s) {
IEnumerable<string> p = s.Split('.');
while (p.Any()) {
yield return string.Join(".", p); // p.ToArray() for .NET 3.5
p = p.Skip(1);
}
}
(I suppose it could be "more efficient" with IndexOf/Substring, but that's also harder for me to write and reason about!)

How to intertwine two strings or arrays, possibly with String.Join()

I have the following string arrays:
var myArray1 = new string[] {"A", "B", "C"};
var myArray2 = new string[] {"t1", "t2"};
I would like to be able to produce a final string that looks like this:
var myFinalString = "t1.A, t2.A, t1.B, t2.B, t1.C, t2.C";
I know I can iterate through each element of the array and build the string manually. However, I'd like to know if there's a better way. I tried to figure out how to make String.Join() method work, but couldn't :-(.
I don't know that any direct method exists, but this one-liner
return
from a in myArray
from b in tTerms
select string.Format("{0}.{1}", b, a)
should do it.
This works:
var query = from x in new[]{"A", "B", "C"}
from y in new[]{"t1", "t2"}
select y + "." + x;
var result = string.Join(", ", query.ToArray());
The term for such sequence is "Cartesian Product".
Here is long blog by Eric Lippert on it Computing a Cartesian Product with LINQ
As it is already shown in other answers sequence of tuples can be obtained with following code and than aggregated (using Join in case of string, or Aggregate for other type of result) to produce your final string:
var product =
from first in s1
from second in s2
select new[] { first, second };
var result String.Join(", ",
product.Select(p => String.Format("{0}.{1}", p.first, p.second));
If the two sequences are of the same length, you could probably put Enumerable.Zip to work for you.
var myFinalString = myArray.Zip(mySecondArray, (f, s) => f + "." + s);

Convert List<Enum> to List<string>

I have a list of enum values:
public static readonly List<NotifyBy> SupportedNotificationMethods = new List<NotifyBy> {
NotifyBy.Email, NotifyBy.HandHold };
I would like to output it as a comma separated list. (EG: "Email, Handhold")
What is the cleanest way of doing this?
Perhaps this:
var str = String.Join(", ", SupportedNotificationMethods.Select(s => s.ToString()));
You can read more about the String.Join method at MSDN. Older versions of String.Join don't have an overload that takes an IEnumerable. In that case just call ToArray() after select.
you can use linq:
string.Join(", ", SupportedNotificationMethods.Select(e => e.ToString());
String.Join(", ", SupportedNotificationMethods.Select(e => e.ToString()).ToArray());

C# Converting ListBox to String then Aggregate

I have a listbox being populated from a combo box. What i need to do is string all the contents of the listbox together and then Aggregate it.
string cols = listbox1.items.Aggregate((f, s) => f.value + "," + s.value);
doesnt work.
Items is an ObjectCollection, so all you know for sure is that it contains objects. You can call ToString on any object:
string[] items = listBox1.Items
.OfType<object>()
.Select(item => item.ToString())
.ToArray();
string result = string.Join(",", items);
Note that this is both more readable and more efficient than using aggregate, which causes multiple string concatenations.
pretty old thread, but here's my solution if anybody need it still
string cols = string.Join(",", listBox1.Items.Cast<String>());
Supposing that you have strings in the listbox, try this:
string cols =
String.Join(",", listbox1.Items
.OfType<Object>()
.Select(i => i.ToString())
.ToArray());
Generally String.Join is used to join a string. This is faster than using a StringBuilder as the size of the new string is already known and it doesn't have to copy everything twice.
string cols = listBox1.Items.Cast<string>().Aggregate((f, s) => f + "," + s);
I think you need to explicitly do ToString()
string cols = listbox1.items.Aggregate((f, s) => f.value.ToString() + "," + s.value.ToString());

Categories