FormatException on String to Int.ToList Conversion - c#

string aresultlist = File.ReadAllLines(data).ToString();
var bresultlist = aresultlist.Split().Select(s => Convert.ToInt32(s));
List<int> resultlist = bresultlist.ToList();
Can anyone help with the FormatException I keep getting on this block, "It's the datetime Format, take date first exception". It's a string read from a space delimited text file.

Try this:
List<int> resultList = File
.ReadLines(data) // you've got IEnumerable<string>
.Select(line => line.Split()) // -/- IEnumerable<string[]>
.Select(ietms => int.Parse(items[0])) // -/- IEnumerable<int>
.ToList(); // finally, it's List<int>
I've assumed that it's the 1st item of the line which should be converted into int: int.Parse(items[0]), change 0 into the right index if required.
Try avoiding ReadAllLines in favor to ReadLines: you don't what all the file (which can be long) to be read into an array in one go

the problem is that ReadAllLines returns a string[]. If you call ToString on such an object you get the namespace.classname as a string. So in your case:
System.String[]
splitting this string results definetely not a number. But in a string[] with on entry, namely:
System.String[]
If your file has only one line with the space delimited numbers, I would suggest to use File.ReadAllText. It will read the entire content of the file and return it as 1 string. This way you can use your code almost as it is.
string aresultlist = File.ReadAllText(data);
var bresultlist = aresultlist.Split().Select(s => Convert.ToInt32(s));
List<int> resultlist = bresultlist.ToList();
EDIT:
As suggested by Gilad Green you might have content in the file that cannot be parsed to a number and will throw an exception. To avoid this you can follow this example

Related

Trouble Converting string [] to int []

using System;
using System.IO;
namespace Test_Arrays_and_Files
{
class Program
{
static void Main(string[] args)
{
string tFile = #"C:\Programming\GLO\DC\dcw.txt";
string read = File.ReadAllText(tFile);
string[] test = read.Split(',');
int[] ints = Array.ConvertAll(test, int.Parse);
Console.WriteLine(ints[0]);
}
}
}
Input Data:
Text File Contents:(1 value per line,)
35,
35,
40,
40,
40,
getting System.FormatException: Input string was not in correct format
please help and sorry for bad post I'm new here
There are two issues in your code,
Your string is ending with , which is creating empty record after the split. This is the reason you are getting the error.
Your delimiter could be $",{Environment.NewLine}" not only ','.
So to convert given string to int array, first Trim() the input string by , and then split by $",{Environment.NewLine}".
Like,
using System.Linq;
...
var result = str.Trim(',') //Remove leading and trailing comma(s), You can use `TrimEnd()` as well
.Split($",{Environment.NewLine}", StringSplitOptions.RemoveEmptyEntries) //Split by given delimiter.
.Select(int.Parse)
.ToArray(); //Convert string[] to int[]
Try online
You're only getting it because the file has a comma at the end, which means Split ends up churning out an empty string in the very last position. int.Parse will choke on the empty string
Plenty of ways you could solve it, one is to tell Split not to return you empties, by changing the split line of your code to:
string[] test = read.Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries);
You could instead trim the comma off the end, but using the above approach would mean your parsing would survive a blank line in the middle of the file too so overall it's more robust
Generally when parsing strings it's more robust to use TryParse than Parse. TryParse takes in the number variable to set the result to and returns you a Boolean telling if the parsing succeeded
int[] ints = Array.ConvertAll(test, GetIntOrMinusOne);
//put a method helper
private int GetIntOrMinusOne(string s){
if(int.TryParse(s, out var t)
return t;
return -1;
}
For this we need to get a bit more involved with the ConvertAll call. Instead of telling ConvertAll to call a "method that converts a string to an int" like int.Parse, we need to write our own mini method that tries to parse and if it fails return something like -1, then nominate that as the method to call to do the conversion, not int.Parse
It's important to note that this would introduce -1 into the resulting int[] array wherever there was bad data in the string array.. In your later processing you would then do some check to avoid them (such as skipping them)
You can shorten that code above by turning the method into a lambda:
int[] ints = Array.ConvertAll(test, s => int.TryParse(s, out var t) ? t : -1);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
a lambda; "just the important parts of a method"
But I'm not sure that you'll have come across lambdas yet, judging by the style of the rest of the code

Taglib artist string error System.String[]

have anyone are a idea why im getting here a Error (I've already tried it with this String f.Tag.Performers.ToString();)
but then the label shows System.String[]
TagLib.File f = TagLib.File.Create(paths[Playlist.SelectedIndex]);
ArtistLabel.Text = f.Tag.Performers; //f.Tag.Performers are the Error
if (f.Tag.Performers == null)
ArtistLabel.Text = "unbekannt";
Presumably this is an array of strings:
f.Tag.Performers
And this is clearly a string:
ArtistLabel.Text
Basically, a basket of apples is not an apple. How do you want the array of strings to display? For example, you might join them separated by commas:
ArtistLabel.Text = string.Join(", ", f.Tag.Performers);
There are a variety of approaches you can take to format your output. The point is that the system doesn't do it for you because it doesn't know what format you want. You can join the array, loop over it and append to the output, bind a set of controls to it, etc.
As error says f.Tag.Performers is of type string[]. Either override .ToString() function or use string.Join() function like
ArtistLabel.Text = string.Join(" ", f.Tag.Performers);

C# LINQ: How is string("[1, 2, 3]") parsed as an array?

I am trying to parse a string into array and find a very concise approach.
string line = "[1, 2, 3]";
string[] input = line.Substring(1, line.Length - 2).Split();
int[] num = input.Skip(2)
.Select(y => int.Parse(y))
.ToArray();
I tried remove Skip(2) and I cannot get the array because of non-int string. My question is that what is the execution order of those LINQ function. How many times is Skip called here?
Thanks in advance.
The order is the order that you specify. So input.Skip(2) skips the first two strings in the array, so only the last remains which is 3. That can be parsed to an int. If you remove the Skip(2) you are trying to parse all of them. That doesn't work because the commas are still there. You have splitted by white-spaces but not removed the commas.
You could use line.Trim('[', ']').Split(','); and int.TryParse:
string line = "[1, 2, 3]";
string[] input = line.Trim('[', ']').Split(',');
int i = 0;
int[] num = input.Where(s => int.TryParse(s, out i)) // you could use s.Trim but the spaces don't hurt
.Select(s => i)
.ToArray();
Just to clarify, i have used int.TryParse only to make sure that you don't get an exception if the input contains invalid data. It doesn't fix anything. It would also work with int.Parse.
Update: as has been proved by Eric Lippert in the comment section using int.TryParse in a LINQ query can be harmful. So it's better to use a helper method that encapsulates int.TryParse and returns a Nullable<int>. So an extension like this:
public static int? TryGetInt32(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}
Now you can use it in a LINQ query in this way:
string line = "[1, 2, 3]";
string[] input = line.Trim('[', ']').Split(',');
int[] num = input.Select(s => s.TryGetInt32())
.Where(n => n.HasValue)
.Select(n=> n.Value)
.ToArray();
The reason it does not work unless you skip the first two lines is that these lines have commas after ints. Your input looks like this:
"1," "2," "3"
Only the last entry can be parsed as an int; the initial two will produce an exception.
Passing comma and space as separators to Split will fix the problem:
string[] input = line
.Substring(1, line.Length - 2)
.Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
Note the use of StringSplitOptions.RemoveEmptyEntries to remove empty strings caused by both comma and space being used between entries.
I think it would be better you do it this way:
JsonConvert.DeserializeObject(line, typeof(List<int>));
you might try
string line = "[1,2,3]";
IEnumerable<int> intValues = from i in line.Split(',')
select Convert.ToInt32(i.Trim('[', ' ', ']'));

Why is this considered going from string[] to int[]?

It keeps giving me an error message here and I don't understand why.
int[] user31 = new int[53];
user31 = System.IO.File.ReadLines("ratings.txt").Skip(1675).Take(53).ToArray();
Because ReadLines returns strings, you know. It is right there in the documentation:
http://msdn.microsoft.com/en-us/library/dd383503(v=vs.110).aspx
and you just do "TOArray".
If you would parse the rows before doing ToArray....
Skip(1675).Take53.Select (x=> Int.Parse(x)).ToArray()
(or along this line)
You would get an array of ints, but calling ToArray on an enum of string returns an array of strings.
Just look at the return type of System.IO.File.ReadLines methods. It is String[].
You call Skip and Take as a result you will have an IEnumerable<String> calling ToArray again will give you a String[] not int[].
Because each line of a text file is just that, text. If you can guarantee that each line is actually an integer, you can do something like this:
int[] user31 = new int[53];
string[] lines = System.IO.File.ReadLines("ratings.txt").Skip(1675).Take(53).ToArray();
int i = 0;
foreach (var line in lines)
{
user31[i++] = Convert.ToInt32(lines[i]);
}
ReadLines returns strings with an array
I assume that your ratings.txt file contain int values in each line
you need to convert string array to int array ..
int[] user31 = new int[53];
user31= System.IO.File.ReadLines("ratings.txt").Skip(1675).Take(53).ToArray().Select(n => Convert.ToInt32(n)).ToArray();
This is because the user31 is an integer array but ReadLine returns string[].
Try like this:
List<string> str =new List<string>(new string[] {"123", "234","345","456","678","678","890"});
List<int> a = str.Skip(1675).Take(53).ConvertAll(new Converter<string, int>(int.Parse));
No need to explicitly parse it yourself and return an array. ConvertAllwill do the job to return an array.
EDIT:
Included a running test case using ConvertAll function.

Array failed to know if it contains a string

I must doing something wrong... But I can't figure it out!
I have an array with string in it. I'm trying to fins if the Array contains some words like Sales for example.
drillDownUniqueNameArray[0] = "[Sales Territory].[Sales Territories].[Sales Territory Group].&[North America]";//Inside the string array there is this string in index 0
drillDownUniqueNameArray.Contains("S")//Output false!
Array.IndexOf(drillDownUniqueNameArray,"S")//Output -1! <--Fixed My answer
drillDownUniqueNameArray.Contains("[Sales Territory].[Sales Territories].[Sales Territory Group].&[North America]") //Output true!
I thouhgt Contains should find even part of the string..
How can I find if this array have "S" or "Sales" for example?
You are asking if the array contains a string that exactly matches "S".
What you want is to ask if any of the strings in the array contains the character "S", something like:
drillDownUniqueNameArray.Any(v => v.Contains("S"))
You're checking if the array contains an element that's exactly "S" but I think you are trying to check whether the array contains an alement that contains an "S".
You could achieve this by the following statement:
drillDownUniqueNameArray.Any( str => str.Contains ("S") )
You can try this.
drillDownUniqueNameArray[0].Contains("s");
You can use LINQ:
var allWithSales = drillDownUniqueNameArray
.Where(str => str.Contains("Sales"));
ignoring the case:
var allWithSalesIgnoreCase = drillDownUniqueNameArray
.Where(str => str.IndexOf("sales", StringComparison.OrdinalIgnoreCase) >= 0);
If you want to find all that contain a word "Sales"(String.Split() = white-space delimiter)):
var allWordsWithSales = drillDownUniqueNameArray
.Where(str => str.Split().Contains("Sales", StringComparer.OrdinalIgnoreCase));
Now you can enumerate the query with foreach or use ToArray() or ToList to create a collection:
foreach(string str in allWithSales)
Console.WriteLine(str);
You are finding it in the array, but you should find the word in the string.
Use following if you want to check:
drillDownUniqueNameArray.Any(x=>x.Contains("Sales"));
Use following if want to get the strings which contains "Sales"
drillDownUniqueNameArray.Where(x=>x.Contains("Sales"));
When you do it like this:
drillDownUniqueNameArray.Contains("S")
it's not gonna check the values, you must do it like this:
drillDownUniqueNameArray[0].Contains("S") or drillDownUniqueNameArray.First().Contains("S")
like this way it checks the values inside the array not the arrays itself

Categories