Convert List<int> to string of comma separated values - c#

having a List<int> of integers (for example: 1 - 3 - 4)
how can I convert it in a string of this type?
For example, the output should be:
string values = "1,3,4";

var nums = new List<int> {1, 2, 3};
var result = string.Join(", ", nums);

var ints = new List<int>{1,3,4};
var stringsArray = ints.Select(i=>i.ToString()).ToArray();
var values = string.Join(",", stringsArray);

Another solution would be the use of Aggregate. This is known to be much slower then the other provided solutions!
var ints = new List<int>{1,2,3,4};
var strings =
ints.Select(i => i.ToString(CultureInfo.InvariantCulture))
.Aggregate((s1, s2) => s1 + ", " + s2);
See comments below why you should not use it. Use String.Join or a StringBuilder instead.

public static string ToCommaString(this List<int> list)
{
if (list.Count <= 0)
return ("");
if (list.Count == 1)
return (list[0].ToString());
System.Text.StringBuilder sb = new System.Text.StringBuilder(list[0].ToString());
for (int x = 1; x < list.Count; x++)
sb.Append("," + list[x].ToString());
return (sb.ToString());
}
public static List<int> CommaStringToIntList(this string _s)
{
string[] ss = _s.Split(',');
List<int> list = new List<int>();
foreach (string s in ss)
list.Add(Int32.Parse(s));
return (list);
}
Usage:
String s = "1,2,3,4";
List<int> list = s.CommaStringToIntList();
list.Add(5);
s = list.ToCommaString();
s += ",6";
list = s.CommaStringToIntList();

You can use the delegates for the same
List<int> intList = new List<int>( new int[] {20,22,1,5,1,55,3,10,30});
string intStringList = string.Join(",", intList.ConvertAll<string>(delegate (int i) { return i.ToString(); });

Use the Stringify.Library nuget package
Example 1 (Default delimiter is implicitly taken as comma)
string values = "1,3,4";
var output = new StringConverter().ConvertFrom<List<int>>(values);
Example 2 (Specifying the delimiter explicitly)
string values = "1 ; 3; 4";
var output = new StringConverter().ConvertFrom<List<int>>(values), new ConverterOptions { Delimiter = ';' });

Related

Quick way to insert a List of strings into a string array definition

I have these variables
string a;
string b;
List<string> StringList = new List<string>();
string c;
I would like to define a new string array like so
string[] StringArray = new string[] {a, b, StringList**.METHODHERE** , c} ;
Is there a neat way to convert the list to the array, flatten it, and add the items to the array?
Right now I have something like
string[] ar = new string[] { };
ar[0] = a;
ar[1] = b;
for (int i = 0; i < RpsPdfFilenamesList.Count(); i++)
{ar[i + 2] = RpsPdfFilenamesList.ElementAt(i);}
ar[2 + RpsPdfFilenamesList.Count()] = c;
But im sure theres a fairly basic method out there that im missing that will reduce this code.
You can insert your strings to List first and then make an array of it:
StringList.Insert(0, a);
StringList.Insert(1, b);
StringList.Add(c);
string[] StringArray = StringList.ToArray();
You can use Array.Copy:
Array.Copy(StringList.ToArray(), 0, StringArray, 2, StringList.Count);
You could use List.CopyTo:
string a = "A"; string b = "B"; string c = "C";
var StringList = new List<string>() { "test1", "test2", "test3" };
string[] StringArray = new string[3 + StringList.Count];
StringArray[0] = a; StringArray[1] = b; StringArray[StringArray.Length - 1] = c;
StringList.CopyTo(StringArray, 2);
Result
A
B
test1
test2
test3
C
Here's a shorter but less efficient approach using LINQ:
StringArray = new[] { a, b }.Concat(StringList).Concat(new[] { c }).ToArray();

construct a string with the index the composition of an integer array

i've code for indexes string. What should I add to the code so that the results of the string become.
if string "hello" to "loleh"
this the code :
public void IndexesString()
{
string karakter = "hello";
int [] IP = {4,5,3,2,1};
string Result;
txtResult.Text = Result; // Result = "loleh"
}
You can use foreach loop and StringBuilder (especially for long strings)
var stringBuilder = new StringBuilder();
foreach(var i in IP)
{
stringBuilder.Append(karakter[i-1]);
}
Result = stringBuilder.ToString();
string str = "hello";
string result = new string(new[] { str[3], str[4], str[2], str[1], str[0], });
More generally, substitute the indices 3, 4 etc. with ip[n] or similar. Can be done in loop of course.
Or what about this:
string str = "hello";
int[] ip = { 3, 4, 2, 1, 0, };
var result = new string(Array.ConvertAll(ip, idx => str[idx]));
The old ConvertAll method of .NET 2 is similar to Linq's Select method, but with arrays.
Possible Linq solution
string karakter = "hello";
int[] IP = { 4, 5, 3, 2, 1 };
String result = new String(IP.Select(i => karakter[i - 1]).ToArray());

A more clean approach to sorting a string into another string

I have a string that might look something like this: "3, 7, 12-14, 1, 5-6"
What i need to do is to change that into a string looking like this: "1, 3, 5, 6, 7, 12, 13, 14"
I have made the following code work, but i would very much appreciated help how to do this a cleaner way with less lines of code:
private string sortLanes(string lanesString)
{
List<string> sortedLanes = new List<string>();
if (lanesString.Contains(',') || lanesString.Contains('-'))
{
List<string> laneParts = lanesString.Split(',').ToList();
foreach (string lanePart in laneParts)
{
if (lanePart.Contains('-'))
{
int splitIndex = lanePart.IndexOf('-');
int lanePartLength = lanePart.Length;
int firstLane = Convert.ToInt32(lanePart.Substring(0, splitIndex));
int lastLane = Convert.ToInt32(lanePart.Substring(splitIndex + 1, lanePartLength - splitIndex - 1));
while (firstLane != lastLane)
{
sortedLanes.Add(firstLane.ToString().Trim());
firstLane++;
}
sortedLanes.Add(lastLane.ToString());
}
else
{
sortedLanes.Add(lanePart.Trim());
}
}
sortedLanes.Sort();
sortedLanes = sortedLanes.OrderBy(x => x.Length).ToList();
lanesString = "";
foreach (string lane in sortedLanes)
{
if (lanesString.Length == 0)
{
lanesString = lane;
}
else
{
lanesString = lanesString + ", " + lane;
}
}
}
else
{
return lanesString;
}
return lanesString;
}
I would first split by the , then convert each value into either a single integer or the desired range. Take the results and reorder them and then concatenate back into a string. Something like this.
string test = "3, 7, 12-14, 1, 5-6";
var items = test.Split(',');
var ints = items.SelectMany(item => Expand(item));
string result = string.Join(", ", ints.OrderBy(i => i).ToArray());
private static IEnumerable<int> Expand(string str)
{
if (str.Contains('-'))
{
var range = str.Split('-');
int begin = int.Parse(range[0]);
int end = int.Parse(range[1]);
for (int i = begin; i <= end; i++)
yield return i;
}
else
yield return int.Parse(str);
}
Of course you might want to add some error checking, but I'll leave that up to you.
This will produce the wanted result (partially based on the incorrect answer from #Tigran):
var parts = "3, 7, 12-14, 1, 5-6".Split(new string[] {", "}, StringSplitOptions.None).ToList();
var finalResult = new List<int>();
foreach(var item in parts)
{
if(item.Contains("-"))
{
var rangeParts = item.Split('-');
var first = int.Parse(rangeParts[0]);
var second = int.Parse(rangeParts[1]);
var result = Enumerable.Range(first, second - first + 1);
finalResult.AddRange(result);
}
else
{
finalResult.Add(int.Parse(item));
}
}
var sorted = finalResult.OrderBy(i => i);
var resultString = string.Join(", ", sorted);
Regex would work nicely here...
static void Main()
{
Assert.AreEqual("1, 3, 5, 6, 7, 12, 13, 14", Transform("3, 7, 12-14, 1, 5-6"));
}
private static string Transform(string input)
{
StringBuilder sb = new StringBuilder();
foreach(Match m in new Regex(#"(?<start>\d+)(?:-(?<end>\d+))?(?:,|$)\s*").Matches(input)
.OfType<Match>().OrderBy(m => int.Parse(m.Groups["start"].Value)))
{
int start = int.Parse(m.Groups["start"].Value);
int end = !m.Groups["end"].Success ? start : int.Parse(m.Groups["end"].Value);
foreach (int val in Enumerable.Range(start, end - start + 1))
sb.AppendFormat("{0}, ", val);
}
if (sb.Length > 0)
sb.Length = sb.Length - 2;//remove trailing comma+space;
return sb.ToString();
}
Update
If I wanted to make it confusing I'd just use a single line of code:
return String.Join(", ",new Regex(#"(?<start>\d+)(?:-(?<end>\d+))?(?:,|$)\s*").Matches(input)
.OfType<Match>().OrderBy(m => int.Parse(m.Groups["start"].Value)).SelectMany(m =>
Enumerable.Range(int.Parse(m.Groups["start"].Value), int.Parse(m.Groups["end"].Success
? m.Groups["end"].Value : m.Groups["start"].Value) - int.Parse(m.Groups["start"].Value) + 1))
.Select(i => i.ToString()).ToArray());
LoL :)
If you like Linq:
string input = "3, 7, 12-14, 1, 5-6";
List<int> all = input.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(r => new
{
Range = r,
Parts = r.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => int.Parse(p))
})
.SelectMany(x => Enumerable.Range(x.Parts.First(), 1 + x.Parts.Last() - x.Parts.First()))
.ToList();
Demo

Recursively Generate Combination Of Every Item in the list

I have a List
List<string> collection = {"a","b"}
I want to give a numerical value i.e. Weight e.g. 2
What I want is:
For the given weight, get all possible combinations:
a0b0, a1b0, a2b0
a0b1, a1b1, a2b1
a0b2, a2b2
where 0,1,2 are the values from 0 to the given weight value
I am struggle to generate it. Please guide?
If you truly need all possible combinations, use this:
List<string> collection = new List<string> {"a","b"};
List<int> numbers = new List<int> { 0, 1, 2 };
var result =
from a in collection
from b in collection
from n1 in numbers
from n2 in numbers
select a + n1 + b + n2;
This results in 36 items:
a0a0, a0a1, a0a2, a1a0,
a1a1,
a1a2,
a2a0,
a2a1,
a2a2,
a0b0,
a0b1,
a0b2,
a1b0,
a1b1,
a1b2,
a2b0,
a2b1,
a2b2,
b0a0,
b0a1,
b0a2,
b1a0,
b1a1,
b1a2,
b2a0,
b2a1,
b2a2, b0b0, b0b1, b0b2, b1b0, b1b1, b1b2, b2b0, b2b1, b2b2
If you only need the combinations you stated in your question, use this:
List<int> numbers = new List<int> { 0, 1, 2 };
var result =
from n1 in numbers
from n2 in numbers
select "a" + n1 + "b" + n2;
This results in only 9 items:
a0b0,
a0b1,
a0b2,
a1b0,
a1b1,
a1b2,
a2b0,
a2b1,
a2b2
Using Recursion:
static void ShowCombination(List<string> mlist, int value,int current=0,string stringleft="")
{
if (current == mlist.Count-1) // if this is the last item in the list
{
for (int m = 0; m <= value; m++) //loop through the value add it to the existing string-stringleft
{
Console.WriteLine(stringleft + mlist[current]+m.ToString());
}
}
else // if there are more than 1 item left in the list
{
string currentstring = mlist[current]; //get current string in the list eg. "a"
stringleft = stringleft + currentstring ; //reset existing string -- eg "a"
for (int m = 0; m <= value; m++) //loop through the value add it to the existing 'stringleft' pass it and the new current index for recursion
{
string stopass = stringleft + m.ToString(); // eg. "a0"; "a1"
ShowCombination(mlist, value, current + 1, stopass);
}
}
}
Usage:
ShowCombination(new List<string>() {"a", "b"}, 2);
Output:
a0b0
a0b1
a0b2
a1b0
a1b1
a1b2
a2b0
a2b1
a2b2
This adds not much to #Daniel's answer, just the way you make your weight dynamic:
int weight = 2;
List<string> collection1 = new List<string>{ "a", "b" };
var collection2 = Enumerable.Range(0, weight + 1);
var combinations=from str1 in collection1
from int1 in collection2
from str2 in collection1
from int2 in collection2
select str1 + int1 + str2 + int2;
foreach (var combi in combinations)
Console.WriteLine(combi);
Edit: If you want all permutations, have a look at this project to see how it's implemented. It's working great.
http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G
For example:
List<string> collection1 = new List<string> { "a", "b", "c", "d" };
var collection2 = Enumerable.Range(0, weight + 1);
collection1 = collection1.Concat(collection2.Select(i => i.ToString())).ToList();
var permutations = new Facet.Combinatorics.Permutations<String>(collection1);
foreach (IList<String> p in permutations)
{
String combi = String.Join("", p);
}

Convert string[] to int[] in one line of code using LINQ

I have an array of integers in string form:
var arr = new string[] { "1", "2", "3", "4" };
I need to an array of 'real' integers to push it further:
void Foo(int[] arr) { .. }
I tried to cast int and it of course failed:
Foo(arr.Cast<int>.ToArray());
I can do next:
var list = new List<int>(arr.Length);
arr.ForEach(i => list.Add(Int32.Parse(i))); // maybe Convert.ToInt32() is better?
Foo(list.ToArray());
or
var list = new List<int>(arr.Length);
arr.ForEach(i =>
{
int j;
if (Int32.TryParse(i, out j)) // TryParse is faster, yeah
{
list.Add(j);
}
}
Foo(list.ToArray());
but both looks ugly.
Is there any other ways to complete the task?
Given an array you can use the Array.ConvertAll method:
int[] myInts = Array.ConvertAll(arr, s => int.Parse(s));
Thanks to Marc Gravell for pointing out that the lambda can be omitted, yielding a shorter version shown below:
int[] myInts = Array.ConvertAll(arr, int.Parse);
A LINQ solution is similar, except you would need the extra ToArray call to get an array:
int[] myInts = arr.Select(int.Parse).ToArray();
EDIT: to convert to array
int[] asIntegers = arr.Select(s => int.Parse(s)).ToArray();
This should do the trick:
var asIntegers = arr.Select(s => int.Parse(s));
To avoid exceptions with .Parse, here are some .TryParse alternatives.
To use only the elements that can be parsed:
string[] arr = { null, " ", " 1 ", " 002 ", "3.0" };
int i = 0;
var a = (from s in arr where int.TryParse(s, out i) select i).ToArray(); // a = { 1, 2 }
or
var a = arr.SelectMany(s => int.TryParse(s, out i) ? new[] { i } : new int[0]).ToArray();
Alternatives using 0 for the elements that can't be parsed:
int i;
var a = Array.ConvertAll(arr, s => int.TryParse(s, out i) ? i : 0); //a = { 0, 0, 1, 2, 0 }
or
var a = arr.Select((s, i) => int.TryParse(s, out i) ? i : 0).ToArray();
C# 7.0:
var a = Array.ConvertAll(arr, s => int.TryParse(s, out var i) ? i : 0);
you can simply cast a string array to int array by:
var converted = arr.Select(int.Parse)
var asIntegers = arr.Select(s => int.Parse(s)).ToArray();
Have to make sure you are not getting an IEnumerable<int> as a return
var list = arr.Select(i => Int32.Parse(i));

Categories