This question already has an answer here:
How to split a number into individual nos
(1 answer)
Closed 6 years ago.
Below is my string.
var str = "1,2,3,4,5";
var strArr = str.split(","); // this gives me an array of type string
List<int> intCol = new List<int>(); //I want integer collection. Like
What I am doing is:-
foreach(var v in strArr)
{
intCol.add(Convert.ToInt(v));
}
Is it right way to do it?
Well that's a way of doing it, certainly - but LINQ makes it a lot easier, as this is precisely the kind of thing it's designed for. You want a pipeline that:
Splits the original string into substrings
Converts each string into an integer
Converts the resulting sequence into a list
That's simple:
List<int> integers = bigString.Split(',').Select(int.Parse).ToList();
The use of int.Parse as a method group is clean here, but if you're more comfortable with using lambda expressions, you can use
List<int> integers = bigString.Split(',').Select(s => int.Parse(s)).ToList();
var numbers = str.Split(',').Select(x => int.Parse(x)).ToList();
But in such cases I would add some error handling in case the item could not be converted to an integer like this:
var strArr = str.Split(',')
.Select(x =>
{
int num;
if (int.TryParse(x, out num))
{
return num;
}
// Parse failed so return -1 or some other value or log it
// or throw exception but then this whole operation will fail
// so it is upto you and your needs to decide what to do in such
// a case.
return -1;
});
Note: Convert.ToInt() will throw a FormatException if the value cannot be converted. TryParse will not.
Related
This question already has an answer here:
Index in the Select projection
(1 answer)
Closed 3 years ago.
I want to create a function that flips a string's order
example: "hi" => "ih"
here is the code I have come out with so far:
public static string Flip(this string Str)
{
char[] chararray = Str.ToCharArray();
string output = "";
chararray. //i dont know what methoud should be used to execute action
return output;
}
the thing is, i want to know within the lambda expression what is the index of the object that is currently selected ex:x in (x => x ) indexOf is not an option as there can be more then one char from the same type
how can I know the index?
edit:
I don't want to know how to reverse a string, I want to know how to find an index of an object in lambda expression
In the Select and Where extension methods of LINQ, you have an overload that takes two parameters in the lambda, the first is the element, the second is the index.
so in your case if you have a char array:
var reversedArray = charArray
.Select((c, i) => new { Element = c, Index = i })
.OrderByDescending(arg => arg.Index)
.Select(arg => arg.Element)
.ToArray();
This is just to demonstrate how to get the index in LINQ extesions methods.
As the question states this is not about how to reverse a string.
Is there a way to achieve this?
I tried:
string str = "{34.10,0,0.00}"; //the string as I get it from Postgres DB
decimal[] won;
won = (decimal[])(str); //Cannot convert type 'string' to 'decimal[]'
What I would ideally want is to get into won:
won[0] = 34.10
won[1] = 0
won[2] = 0.00
Surely, I can go and split by commas, and put it in the array but I'm wondering if there's a better way.
You have to Split
won = str.Trim('{', '}').Split(',').Select(decimal.Parse).ToArray();
Edit: This part is just for fun
There is no way to cast string to a decimal[] array directly, but if you want you can add a decimal wrapper class and define implicit conversions:
class MyDecimal
{
private decimal[] _values;
public MyDecimal(int size)
{
_values = new decimal[size];
}
public decimal this[int index]
{
get { return _values[index]; }
set { _values[index] = value; }
}
public static implicit operator MyDecimal(string str)
{
var numbers = str.Trim('{', '}').Split(',');
MyDecimal d = new MyDecimal(numbers.Length);
d._values = numbers
.Select(x => decimal.Parse(x,CultureInfo.InvariantCulture))
.ToArray();
return d;
}
public static implicit operator string(MyDecimal md)
{
return string.Join(",", md._values);
}
}
Then you can do:
string str = "{34.10,0,0.00}"; //the string as I get it from Postgres DB
MyDecimal won = str;
I first misread your question. The real answer is: I know of no other way than splitting and converting in loops or using LINQ (for a LINQ sample see Selman22's answer). There's no way to cast a string to an array in one go.
While it is essentially what you suggest, you could try this:
// Remove leading and trailing brackets
string s = str.Trim('{', '}');
// Split numbers
string[] parts = s.Split(',');
decimal[] nums = new decimal[parts.Length];
// Convert
for (int i = 0; i < parts.Length; i++)
nums[i] = Convert.ToDecimal(parts[i]);
Just to play devil's advocate to those who say you have no option but to split:
var result = new JavaScriptSerializer()
.Deserialize<decimal[]>(str.Replace('{', '[').Replace('}', ']'))
here is another but probably not a better way in regex
string str = "{34.10,0,0.00}";
string pattern = #"([\d]+[\.]|[\d]?)[\d]+";
decimal[] result = Regex.Matches(str, pattern, RegexOptions.None)
.Cast<Match>()
.Select(x => decimal.Parse(x.Value))
.ToArray();
but remember Jamie Zawinski:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Another way would be using a StringReader and managing the split
There is no better way. At least until C# is backed up by an AI which will just guess what you are trying to do by casting one datatype into another by a custom logic.
Any programmer would guess what you want. Until now though the C# compiler is no wizard.
I am completely new to C#. I am trying to loop through a short array, where the string elements in the array are placed at the end of a website search. The code:
int n = 1;
string[] s = {"firstitem","seconditem","thirditem"}
int x = s.Max(); // note, from my research this should return the maximum value in the array, but this is the first error
x = x + 1
while (n < x)
{
System.Diagnostics.Process.Start("www.website.com/" + b[0]);
b[]++; // this also generates an error "identifier expected"
}
My coding, logic or both are wrong. Based on what I've read, I should be able to get the maximum value in an array (as an int), then add to the arrays value while a WHILE loop adds each value in the array at the end of the website (and then stops). Note, that on the first error, I tried coding it differently, like the below:
int x = Convert.ToInt32(s.Max);
However, it generates an overload error. If I'm reading things correctly, MAX should find the maximum value in a sequence.
foreach(var str in s)
{
System.Diagnostics.Process.Start("www.website.com/" + str);
}
You have a collection of strings. The largest string is still a string, not an int. Since s.Max() is a string, and you're assinging it to a variable of type int: int x = s.Max(); the compiler (correctly) informs you that the types do not match. You need to convert that string to an int. Since, looking at your data, they aren't integers, and I see no sensible way of converting those strings into integers, I see no reasonable solution. What integer should "firstitem" be?
If you just want to execute some code for each item in the array then use one of these patterns:
foreach(string item in s)
{
System.Diagnostics.Process.Start("www.website.com/" + item);
}
or
for(int i = 0; i < s.Length; i++)
{
System.Diagnostics.Process.Start("www.website.com/" + s[i]);
}
You're missing a couple of semi-colons
x should presumably be the Length of the array, not the largest value in it
You need to increment x inside of your loop - at the end of it, not outside of it
You should actually be incrementing n, not x
n should be starting at 0, not at 1
Inside the loop you're using b[0] where you probably want to use b[n]
I'm no C++ guru, but I have no idea what b[]++ might mean
As other answers have mentioned, you may want to use a for or foreach instead of a while.
Make an effort to go through some introductory tutorials. Trial and error can be a useful tool, but there's no need to fall back on that when learning the very basics
Following is an image to point out what are the errors of your code:
After the correction, it would be:
int n=1;
string[] s= { "firstitem", "seconditem", "thirditem" };
int x=s.Length;
while(n<x) {
System.Diagnostics.Process.Start("www.website.com/"+s[n]);
n++; // or ++n
}
And we can make it more semantic:
var items=new[] { "firstitem", "seconditem", "thirditem" };
for(int index=1, count=items.Length; index<count; ++index)
Process.Start("www.website.com/"+items[index]);
If the starting order doesn't matter, and we can use foreach instead, and we can use Linq to make the code even simpler:
var list=(new[] { "firstitem", "seconditem", "thirditem" }).ToList();
list.ForEach(item => Process.Start("www.website.com/"+item));
and we might quite often write in another form:
foreach(var item in new[] { "firstitem", "seconditem", "thirditem" })
Process.Start("www.website.com/"+item);
from the sample
var processList = (new string[]{"firstitem","seconditem","thirditem"})
.Select(s => Process.Start("www.website.com/" + s))
.ToList();
and here is a test version that outputs to console
(new string[] { "firstitem", "seconditem", "thirditem" })
.Select(s => { Console.WriteLine(#"www.website.com/" + s); return s; })
.ToList();
note: Select requires a return type and the .ToList() enforces evaluation.
I have a file with int values in each line (although it's possible that some values are not ints like some comments). But the structure of the file is:
1
2
3
4
5
6
7
#some comment
9
10
etc...
What's the fastest way to convert it to IEnumerable. I could read line by line and use List and call Add method, but I guess it's not the best in terms of performance.
Thanks
You could create your IEnumerable on-the-fly while reading the file:
IEnumerable<Int32> GetInts(string filename)
{
int tmp = 0;
foreach(string line in File.ReadLines(filename))
if (Int32.TryParse(line, out tmp))
yield return tmp;
}
This way, you can do whatever you want to do with your integers while reading the file, using a foreach loop.
foreach(int i in GetInts(#"yourfile"))
{
... do something with i ...
}
If you just want to create a list, simply use the ToList extension:
List<Int32> myInts = GetInts(#"yourfile").ToList();
but there probably won't be any measurable performance difference if you "manually" create a list as you described in your question.
var lines = File.ReadLines(path).Where(l => !l.StartsWith("#"));
you can also append .Select(x => int.Parse(x))
public static IEnumerable<int> ReadInts(TextReader tr)
{
//put using here to have this manage cleanup, but in calling method
//is probably better
for(string line = tr.ReadLine(); line != null; line = tr.ReadLine())
if(line.Length != 0 && line[0] != '#')
yield return int.Parse(line);
}
I assume from your description that a line that doesn't match should throw an exception, but I guessed also that blank lines where you don't want them are very common, so I do cathc that case. Adapt to catch that as appropriate otherwise.
If you want to add lines only if they are convertible to ints, you could use int.TryParse. I suggest to use File.ReadLines instead of File.ReadAllLines(creates an array in memory):
int value;
IEnumerable<String>lines = File.ReadLines(path)
.Where(l => int.TryParse(l.Trim(), out value));
or (if you want to select those ints):
int value;
IEnumerable<int>ints= File.ReadLines(path)
.Where(l => int.TryParse(l.Trim(), out value))
.Select(l => value);
I need to convert a string of comma separated integers into a list of integers.
What is the best way to do this?
I can do it below but am worried about the performance - Is there a better more efficient way to do this?
public IEnumerable<int> GetListOfIds()
{
string Ids = "1,4,5,7,12"; // would be passed into method
List<int> _result = Ids.Split(',')
.ToList()
.Select(item => int.Parse(item))
.ToList();
return _result;
}
There's no need to call ToList, but otherwise your code looks fine:
public IEnumerable<int> GetListOfIds(string ids)
{
return ids.Split(',').Select(item => int.Parse(item));
}
You may also want to consider adding error handling in case the input string is invalid:
public IEnumerable<int> GetListOfIds(string ids)
{
foreach (string part in ids.Split(','))
{
int x;
if (!int.TryParse(part, out x))
{
throw new ArgumentException(
string.Format("The value {0} cannot be parsed as an integer.", part),
"ids");
}
else
{
yield return x;
}
}
}
You may at least omit first ToList() statement - so it will be
List<int> _result = Ids.Split(',').Select(item => int.Parse(item)).ToList();
You can probably loop on the split result and do a yield return int.Parse... but I would not expect big differences unless you have really many items in the original string.
Use the Stringify.Library nuget package
Example 1 (Default delimiter is implicitly taken as comma)
var ids = "1, 4, 5, 7, 12";
var splitComma = new StringConverter().ConvertTo<List<int>>(ids);
Example 2 (Specifying the delimiter explicitly)
var ids = "1; 4; 5; 7; 12";
var splitColon = new StringConverter().ConvertTo<List<int>>(ids, new ConverterOptions { Delimiter = ';' });