I was able to convert comma separated string to an IList<int>
but how can I modify the same to get IList<T>
where T will be passed as one of the input parameter?
i.e if I need IList<int>
I will pass "int" as parameter, if I need IList<string>
I will pass "string" as parameter.
My idea is to get the type whether it is int or string through input parameter and use reflection and convert the string to respective list
Code to convert comma separated string as IList<int>
public static IList<int> SplitStringUsing(this string source, string seperator =",")
{
return source.Split(Convert.ToChar(seperator))
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(int.Parse).ToList();
}
Note: Above code isn't tested yet
I am looking for something like
public static IList<T> SplitStringUsing(this string source, string seperator =",", T t)
{
find the type of t and convert it to respective List
}
You can use Convert.ChangeType(object,string) for parsing to the base types supported by the System.Convert class, or any other class that implements the IConvertible interface
public static IList<T> SplitStringUsing<T>(string source, string seperator = ",")
where T:IConvertible
{
return source.Split(Convert.ToChar(seperator))
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x=>Convert.ChangeType(x,typeof(T)))
.Cast<T>()
.ToList();
}
To avoid localization issues, you should probably add an IFormatProvider parameter as well, to allow the caller to specify the culture to use or default to the current culture, eg:
public static IList<T> SplitStringUsing<T>(string source,
string seperator = ",",
IFormatProvider provider =null)
where T:IConvertible
{
return source.Split(Convert.ToChar(seperator))
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x=>Convert.ChangeType(x,typeof(T),provider))
.Cast<T>().ToList();
}
For a more generic case, you can pass the parsing code as a lambda to the function:
public static IList<T> SplitStringUsing<T>(string source,
Func<string,T> parser,
string seperator = ",")
{
return source.Split(Convert.ToChar(seperator))
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(parser)
.ToList();
}
and call it like this:
var l1 = SplitStringUsing(x,s=>double.Parse(s,NumberStyles.HexNumber,
CultureInfo.InvariantCulture));
You can have both methods in your code and the compiler will pick the correct overload.
I think you need Convert.ChangeType, like this. Its not fully tested, compile and fix.
public static IList<T> SplitStringUsing(string source, string seperator =",")
{
return source.Split(Convert.ToChar(seperator))
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select((T)Convert.ChangeType( x, typeof( T ) )).ToList();
}
I would like to extend the answer of @PanagiotisKanavos.
Especially the generic approach with:
public static class StringToListExtension
{
//see https://msdn.microsoft.com/en-us/library/System.String.Split.aspx
//and https://msdn.microsoft.com/en-us/library/bb548891.aspx
//this is the generic approach offering enough possibilies to use
public static IEnumerable<TResult> MapStringValues<TResult>(this String source, Func<String, TResult> itemMapper, String[] separator, StringSplitOptions options)
{
if (null == source) throw new ArgumentNullException("source");
return source.Split(separator, options).Select(itemMapper);
}
//add your implementation using MapStringValues<T>
public static IList<Int32> MapToInt32ListUsingParse(this String source, String[] separator, StringSplitOptions options)
{
return MapStringValues<Int32>(source, Int32.Parse, separator, options).ToList();
}
//or more convenient
public static IList<Int32> DefaultMapToIntList(this String source)
{
return MapStringValues<Int32>(source, Int32.Parse, DefaultSeparator, StringSplitOptions.RemoveEmptyEntries).ToList();
}
private static readonly String[] DefaultSeparator = new []{ "," };
}
You would use that code:
String values = "some,text,with,commas";
List<String> l1 = values.MapStringValues<String>(s => s, new []{ "," }, StringSplitOptions.None).ToList();
values = "2,4,,5,6";
IList<Int32> l2 = values.MapToInt32ListUsingParse(new []{ "," }, StringSplitOptions.RemoveEmptyEntries);
values = "2,4,,5,6";
IList<Int32> l3 = values.DefaultMapToIntList();
You can add convenience implementations for all your String to T cases. If you don't want exceptions to be thrown just implement a parse function using Int32.TryParse, etc.