TryParsing from an object list to int | c# - c#

I'm trying to take objects out of an object list to an int list. If the object list's value contains a string than I want to convert it to an int. the error that I'm getting is "cannot convert from 'object' to 'System.ReadOnlySpan'. I've tried looking up examples and information about lists made of objects but couldn't find anything.
I'm also at a loss as to what to do with the 'else' part of the code.
public class ListFilterer
{
public static IEnumerable(int) GetIntegersFromList(List(object) listOfItems)
{
List<int> Integers = new List<int>();
foreach (var value in listOfItems)
{
int number = 0;
bool success = Int32.TryParse(value, out number);
if (success)
{
Integers.Add(number);
}
else
{
Integers.Add(number);
}
}
return Integers;
}
}

It'll probably work out if you TryParse value.ToString() instead, if you're looking for anything that might look like an int and can be converted to an int. If you only want things that actually are ints, something like if(value is int number) should work if your c# version is recent. If it's older you may have to if(value is int) and then cast the value inside the if
Your code can be simplified to:
foreach(...){
int.TryParse(value.ToString(), out var n);
integers.Add(n);
}
Or
foreach(...){
if(value is int)
integers.Add((int)value);
else
integers.Add(0);
}

You could simply use:
var ints = listOfItems
.Select(o => { int.TryParse(o.ToString(), out int num); return num;} )
.ToList();
This will work as you wish, as if conversion fails num is 0 by default.

If Try Parse fails number is automatically 0 so you can directly write this
Int32.TryParse(value, out int number)
Integers.Add(number);

Maybe you can find the better way
var intList = objs.ConvertAll(delegate (object obj) { return (int)obj; });

Related

Null Values Exception handling in Linq C# [duplicate]

I only found a way to do it the opposite way round: create a comma separated string from an int list or array, but not on how to convert input like string str = "1,2,3,4,5"; to an array or list of ints.
Here is my implementation (inspired by this post by Eric Lippert):
public static IEnumerable<int> StringToIntList(string str)
{
if (String.IsNullOrEmpty(str))
{
yield break;
}
var chunks = str.Split(',').AsEnumerable();
using (var rator = chunks.GetEnumerator())
{
while (rator.MoveNext())
{
int i = 0;
if (Int32.TryParse(rator.Current, out i))
{
yield return i;
}
else
{
continue;
}
}
}
}
Do you think this is a good approach or is there a more easy, maybe even built in way?
EDIT: Sorry for any confusion, but the method needs to handle invalid input like "1,2,,,3" or "###, 5," etc. by skipping it.
You should use a foreach loop, like this:
public static IEnumerable<int> StringToIntList(string str) {
if (String.IsNullOrEmpty(str))
yield break;
foreach(var s in str.Split(',')) {
int num;
if (int.TryParse(s, out num))
yield return num;
}
}
Note that like your original post, this will ignore numbers that couldn't be parsed.
If you want to throw an exception if a number couldn't be parsed, you can do it much more simply using LINQ:
return (str ?? "").Split(',').Select<string, int>(int.Parse);
If you don't want to have the current error handling behaviour, it's really easy:
return text.Split(',').Select(x => int.Parse(x));
Otherwise, I'd use an extra helper method (as seen this morning!):
public static int? TryParseInt32(string text)
{
int value;
return int.TryParse(text, out value) ? value : (int?) null;
}
and:
return text.Split(',').Select<string, int?>(TryParseInt32)
.Where(x => x.HasValue)
.Select(x => x.Value);
or if you don't want to use the method group conversion:
return text.Split(',').Select(t => t.TryParseInt32(t)
.Where(x => x.HasValue)
.Select(x => x.Value);
or in query expression form:
return from t in text.Split(',')
select TryParseInt32(t) into x
where x.HasValue
select x.Value;
Without using a lambda function and for valid inputs only, I think it's clearer to do this:
Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);
--EDIT-- It looks like I took his question heading too literally - he was asking for an array of ints rather than a List --EDIT ENDS--
Yet another helper method...
private static int[] StringToIntArray(string myNumbers)
{
List<int> myIntegers = new List<int>();
Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
{
int currentInt;
if (Int32.TryParse(s, out currentInt))
myIntegers.Add(currentInt);
});
return myIntegers.ToArray();
}
quick test code for it, too...
static void Main(string[] args)
{
string myNumbers = "1,2,3,4,5";
int[] myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 15.
myNumbers = "1,2,3,4,5,6,bad";
myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 21
Console.ReadLine();
}
Let us assume that you will be reading the string from the console. Import System.Linq and try this one:
int[] input = Console.ReadLine()
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
This has been asked before. .Net has a built-in ConvertAll function for converting between an array of one type to an array of another type. You can combine this with Split to separate the string to an array of strings
Example function:
static int[] ToIntArray(this string value, char separator)
{
return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
}
Taken from here
This is for longs, but you can modify it easily to work with ints.
private static long[] ConvertStringArrayToLongArray(string str)
{
return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}
I don't see why taking out the enumerator explicitly offers you any advantage over using a foreach. There's also no need to call AsEnumerable on chunks.
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
String line;
String[] lineVector;
int n,m,i,j;
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
lineVector = line.split(",");
//enter the size of the array
n=Integer.parseInt(lineVector[0]);
m=Integer.parseInt(lineVector[1]);
int arr[][]= new int[n][m];
//enter the array here
System.out.println("Enter the array:");
for(i=0;i<n;i++)
{
line = sc.nextLine();
lineVector = line.split(",");
for(j=0;j<m;j++)
{
arr[i][j] = Integer.parseInt(lineVector[j]);
}
}
sc.close();
}
}
On the first line enter the size of the array separated by a comma. Then enter the values in the array separated by a comma.The result is stored in the array arr.
e.g
input:
2,3
1,2,3
2,4,6
will store values as
arr = {{1,2,3},{2,4,6}};

Check if value is in Enum range without using IsDefined

There are a few other Questions on how to convert Enums and what happens if the value parsed is out-of-range, like in:
public enum SomeTypes
{
SomeType1 = 1,
SomeType2 = 2,
SomeType3 = 3
}
public class SomeClass
{
...
var inRange = (SomeTypes) 1;
var outOfRange = (SomeTypes) 5;
...
}
Going out-of-range will not produce any error.
But I found the hard way that if you try to serialize-deserialize an enum with an out-of-range value you'll get weird errors. For example, I was getting something like
"error parsing the message or timeout exceeded"
which kept me looking for other reasons than the enum out-of-range.
Suggestions to handle this are by the means of the Enum.IsDefined. That seems to work quite nicely, but then there's this rather bold warning on msdn:
"Do not use System.Enum.IsDefined(System.Type,System.Object) for enumeration range checks as it is based on the runtime type of the enumeration, which can change from version to version."
So, my question is, can we safely use Enum.IsDefined or what is the correct way to check if the value of an enum is out-of-range without using the Enum.IsDefined?
Use Enum.GetValues():
public bool IsInRange(int value){
var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x);
return value >= values.First() && value <= values.Last();
}
[EDIT]
In case you want to check if the item is defined instead of just checking if it's inside the range, you can do similarly:
public bool IsDefined(int value){
var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x);
return values.Contains(value);
}
There is an option for something simpler:
int value;
bool isInRange = string.IsNullOrEmpty(Enum.GetName(typeof(myEnumType), value));
I did a similar thing with objects DataContract
You must decorate the items in the list with [EnumMember] and then you could obtain the enum name with this method. So you would know if value exists in the enum cos returns his enum name.
public static string GetEnumNameFromValue(System.Type typeEnum, string value)
{
FieldInfo[] fis = typeEnum.GetFields();
foreach (FieldInfo fi in fis)
{
EnumMemberAttribute[] attributes = (EnumMemberAttribute[])fi.GetCustomAttributes(typeof(EnumMemberAttribute), false);
if (attributes.Length > 0)
{
if (string.Compare(attributes[0].Value, value, true) == 0)
{
return fi.Name;
}
}
}
return null;
}

What's the correct way to not update an out variable

I've implemented a TryParse function for a class MinMax like this:
public static bool TryParse(string s, out MinMax result)
{
var parts = s.Split(' ');
if (parts.Length != 2)
{
return false;
}
float min;
float max;
if (!float.TryParse(parts[0].Trim(), out min) || !float.TryParse(parts[1].Trim(), out max))
{
return false;
}
result = new MinMax(min, max);
return true;
}
However this doesn't compile since apparently the out parameter needs to be written. What's the correct way to fix this? I would like to be able to use the function so that if the parsing fails, the parameter passed into it remains unchanged. I guess one way would be to add something like:
result = result;
but this line issues a warning.
Pass by ref:
public static bool TryParse(string s, ref MinMax result)
which means you will have to ensure the result parameter is initialised.
Update: It is better to stick to the well known semantics of TryParse. (I'm sometimes critised for answering the real question not the one that was asked! On this occasion it was the opposite!)
Assuming MinMax is a reference type, just assign null to it. Just like any other TryParse method would work.
Check out this code:
string s = "12dfsq3";
int i = 444;
int.TryParse(s, out i);
Console.WriteLine(i);
i will be set to 0 instead of remaining at 444.
Given that an out parameter doesn't even need to be initialized by the caller, you really have to do something with it.
You could use a ref parameter instead, those don't require you to touch them in your function.
I don't like these answers telling you to use a ref parameter as it changes the semantics of the method and will require callers to pass an initialised value.
Set result to the default value for MinMax, which is null if it's a reference type, or use the default operator.
result = default(MinMax);
The only correct way to not update an out variable is to throw an exception. Change out to ref.
You have to set the value of the out variable. You could use ref as other answers have suggested, but I wouldn't recommend it - that's not how the standard TryParse pattern is supposed to work. Besides, it's ugly and unnecessary.
It doesn't really matter what result contains in the failure case, since the bool that you return indicates whether the parsing was successful or not. Just return new MinMax(0, 0) or, if you prefer, default(MinMax):
public static bool TryParse(string s, out MinMax result)
{
string[] parts = s.Split(' ');
if (parts.Length == 2)
{
float min, max;
if (float.TryParse(parts[0].Trim(), out min)
&& float.TryParse(parts[1].Trim(), out max))
{
result = new MinMax(min, max);
return true;
}
}
result = default(MinMax); // or just use "result = new MinMax(0, 0);"
return false;
}

Cascading parse

I may have the following types:
Number with decimal : 100.90
Number (int32) : 32
String : ""
What I want is a function which tries to parse as a decimal and if it fails, then tries to parse as an int and if that fails then its a string.
Any sort of function in C# which has the following functionality is appreciated.
public static object cascadeParse(string obj)
{
decimal decRet;
if (!decimal.TryParse(obj, out decRet))
{
int intRet;
if (!int.TryParse(obj, out intRet))
{
return obj;
}
else
{
return intRet;
}
}
else
{
return decRet;
}
}
However this method will always return a decimal when passed something that can be parsed as an int as ints can always be parsed as decimal. You may want to re-order the TryParses to put the int one first.
TryParse() is your friend, however I don't understand what you want as all valid ints are also valid decimals.

Convert comma separated string of ints to int array

I only found a way to do it the opposite way round: create a comma separated string from an int list or array, but not on how to convert input like string str = "1,2,3,4,5"; to an array or list of ints.
Here is my implementation (inspired by this post by Eric Lippert):
public static IEnumerable<int> StringToIntList(string str)
{
if (String.IsNullOrEmpty(str))
{
yield break;
}
var chunks = str.Split(',').AsEnumerable();
using (var rator = chunks.GetEnumerator())
{
while (rator.MoveNext())
{
int i = 0;
if (Int32.TryParse(rator.Current, out i))
{
yield return i;
}
else
{
continue;
}
}
}
}
Do you think this is a good approach or is there a more easy, maybe even built in way?
EDIT: Sorry for any confusion, but the method needs to handle invalid input like "1,2,,,3" or "###, 5," etc. by skipping it.
You should use a foreach loop, like this:
public static IEnumerable<int> StringToIntList(string str) {
if (String.IsNullOrEmpty(str))
yield break;
foreach(var s in str.Split(',')) {
int num;
if (int.TryParse(s, out num))
yield return num;
}
}
Note that like your original post, this will ignore numbers that couldn't be parsed.
If you want to throw an exception if a number couldn't be parsed, you can do it much more simply using LINQ:
return (str ?? "").Split(',').Select<string, int>(int.Parse);
If you don't want to have the current error handling behaviour, it's really easy:
return text.Split(',').Select(x => int.Parse(x));
Otherwise, I'd use an extra helper method (as seen this morning!):
public static int? TryParseInt32(string text)
{
int value;
return int.TryParse(text, out value) ? value : (int?) null;
}
and:
return text.Split(',').Select<string, int?>(TryParseInt32)
.Where(x => x.HasValue)
.Select(x => x.Value);
or if you don't want to use the method group conversion:
return text.Split(',').Select(t => t.TryParseInt32(t)
.Where(x => x.HasValue)
.Select(x => x.Value);
or in query expression form:
return from t in text.Split(',')
select TryParseInt32(t) into x
where x.HasValue
select x.Value;
Without using a lambda function and for valid inputs only, I think it's clearer to do this:
Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);
--EDIT-- It looks like I took his question heading too literally - he was asking for an array of ints rather than a List --EDIT ENDS--
Yet another helper method...
private static int[] StringToIntArray(string myNumbers)
{
List<int> myIntegers = new List<int>();
Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
{
int currentInt;
if (Int32.TryParse(s, out currentInt))
myIntegers.Add(currentInt);
});
return myIntegers.ToArray();
}
quick test code for it, too...
static void Main(string[] args)
{
string myNumbers = "1,2,3,4,5";
int[] myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 15.
myNumbers = "1,2,3,4,5,6,bad";
myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 21
Console.ReadLine();
}
Let us assume that you will be reading the string from the console. Import System.Linq and try this one:
int[] input = Console.ReadLine()
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
This has been asked before. .Net has a built-in ConvertAll function for converting between an array of one type to an array of another type. You can combine this with Split to separate the string to an array of strings
Example function:
static int[] ToIntArray(this string value, char separator)
{
return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
}
Taken from here
This is for longs, but you can modify it easily to work with ints.
private static long[] ConvertStringArrayToLongArray(string str)
{
return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}
I don't see why taking out the enumerator explicitly offers you any advantage over using a foreach. There's also no need to call AsEnumerable on chunks.
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
String line;
String[] lineVector;
int n,m,i,j;
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
lineVector = line.split(",");
//enter the size of the array
n=Integer.parseInt(lineVector[0]);
m=Integer.parseInt(lineVector[1]);
int arr[][]= new int[n][m];
//enter the array here
System.out.println("Enter the array:");
for(i=0;i<n;i++)
{
line = sc.nextLine();
lineVector = line.split(",");
for(j=0;j<m;j++)
{
arr[i][j] = Integer.parseInt(lineVector[j]);
}
}
sc.close();
}
}
On the first line enter the size of the array separated by a comma. Then enter the values in the array separated by a comma.The result is stored in the array arr.
e.g
input:
2,3
1,2,3
2,4,6
will store values as
arr = {{1,2,3},{2,4,6}};

Categories