I got a textbox that should be filled with int of 4 number, something like this [0000, 4444, 5555, 6666]. I need to get where is the comma and then put the 4 numbers in a var.
Can you help me?
Have you tried String.Split?
string[] allTokens = textBox1.Text.Split(new []{ ','}, StringSplitOptions.RemoveEmptyEntries);
int[] allInts = Array.ConvertAll<string, int>(allTokens, int.Parse);
If the format can be invalid you can use int.TryParse:
int num = 0;
int[] allInts = allTokens
.Where(s => int.TryParse(s, out num))
.Select(s => num)
.ToArray();
You will get int list
var numbers = TextBox1.Text.Split(',').Select(str => {
int value;
bool success = int.TryParse(str, out value);
return new { value, success };
})
.Where(pair => pair.success)
.Select(pair => pair.value).ToList();
Reference
You could try
var resultArr = tb.split(",");
foreach (elem in resultArr)
{
int i;
if (int.tryparse(elem, out i))
// do something with i
else
// that was not an int
}
Related
I've converting comma separated string to List.
Problem while a list contain empty value or invalid value, how to skip invalid value?
List<int> list = model.Categories.Split(',').Select(int.Parse).ToList();
string will be "10,12,3.0,4,1k,5,0.0";
If you wanna validate that only valid ints will reach the Select use int.TryParse:
int num;
var result = model.Categories.Split(',')
.Where(i => int.TryParse(i, out num))
.Select(int.Parse).ToList();
If using C#7.0 then can just be:
var result = model.Categories.Split(',')
.Where(i => int.TryParse(i, out int num))
.Select(int.Parse).ToList();
To not have to parse twice you can try something like this too:
Func<string, int?> ParseOrDefault = (input) =>
int.TryParse(input, out int num) ? (int?)num : null;
var result = data.Split(',').Select(ParseOrDefault).Where(i => i != null).ToList();
Or better:
var result = data.Split(',')
.Select(i => int.TryParse(i, out int num) ? (int?)num : null)
.Where(i => i != null).ToList();
You can try using TryParse instead of Parse:
List<int> list = model
.Categories
.Split(',')
.Select(item => {
int value;
bool parsed = int.TryParse(item, out value);
return new {
parsed = parsed,
value = value;
};
})
.Where(item => item.parsed)
.Select(item => item.value)
.ToList();
I need to have the numbers a user inputs added. The numbers will come from a single textbox and are separated by a comma. an example of numbers that can be used are 7,9,10,2,18,6.
Here is my code so far
private void calculateButton_Click(object sender, EventArgs e)
{
string str = inputNumbTextBox.Text;
char[] delim = { ',' };
string[] tokens = str.Split(delim);
if (char.IsDigit(str, 0))
{
}
else
{
MessageBox.Show("Please enter a number");
}
}
Thanks in advance.
use int.TryParse instead of char.IsDigit:
int sum = 0;
string[] tokens = str.Split(delim);
foreach(string str in tokens)
{
int value = 0;
if (int.TryParse(str, out value))
{
sum += value;
}
}
This works for me:
var text = "7,9,10,2,18,6";
var sum =
text
.Split(new [] { ',' })
.Select(x => int.Parse(x.Trim()))
.Sum();
I get the result 52.
I would typically go one step further and define a cleaning function like so:
Func<string, int?> clean = x =>
{
var r = (int?)null;
int v;
if (int.TryParse(x.Trim(), out v))
{
r = v;
}
return r;
};
Then I could separate out any extract logic needed to validate the input. Now my summing query would look like this:
var sum =
text
.Split(new [] { ',' })
.Select(x => clean(x))
.Where(x => x.HasValue)
.Sum();
IF in a string there is a character or characters that occurs again and again. Like in the following string:
1+1+1-2+2/2*4-2*3/23
Now in the string above the + occurs 3 times at the indexes of 1,3,7 and - occurs 2 times at the indexes of 5,13 and so others, and then storing them in 2 dimensional array So now the issue is that how to do this.
The following function will return all matched indices for a given search string:
List<int> GetAllIndices(string input, string search)
{
List<int> result = new List<int>();
int index = input.IndexOf(search);
while(index != -1)
{
result.Add(index);
index++;//increment to avoid matching the same index again
if(index >= input.Length)//check if index is greater than string (causes exception)
break;
index = input.IndexOf(search, index);
}
return result;
}
It should also handle overlapping matches, for example: searching "iii" for occurrences of "ii" will return [0,1]
If you want to use this function to create a list of symbols and their indices then I would recommend the following approach:
string input = "1+1+1-2+2/2*4-2*3/23";
//create a dictionary to store the results
Dictionary<string, List<int>> results = new Dictionary<string, List<int>>();
//add results for + symbol
results.Add("+", GetAllIndices(input, "+"));
//add results for - symbol
results.Add("-", GetAllIndices(input, "-"));
//you can then access all indices for a given symbol like so
foreach(int index in results["+"])
{
//do something with index
}
You could even go a step further and wrap that in a function that searches for multiple symbols:
Dictionary<string, List<int>> GetSymbolMatches(string input, params string[] symbols)
{
Dictionary<string, List<int>> results = new Dictionary<string, List<int>>();
foreach(string symbol in symbols)
{
results.Add(symbol, GetAllIndices(input, symbol));
}
return results;
}
Which you can then use like so:
string input = "1+1+1-2+2/2*4-2*3/23";
Dictionary<string, List<int>> results = GetSymbolMatches(input, "+", "-", "*", "/");
foreach(int index in results["+"])
{
//do something with index
}
With Linq:
var allIndices = yourString.Select((c, i) => new { c, i, })
.Where(a => a.c == '+').Select(a => a.i);
To get a dictionary with all characters in the string, for example:
var allCharsAllIndices = yourString.Select((c, i) => new { c, i, })
.GroupBy(a => a.c)
.ToDictionary(g => g.Key, g => g.Select(a => a.i).ToArray());
you can try this with changing 'value'
var duplicates = param1.ToCharArray().Select((item, index) => new { item, index })
.Where(x =>x.item==VALUE).GroupBy(g=>g.index)
.Select(g => new { Key = g.Key })
.ToList();
string msg = "1+1+1-2+2/2*4-2*3/23";
Dictionary<char, List<int>> list = new Dictionary<char, List<int>>();
for (int i = 0; i < msg.Length; i++)
{
if (!list.ContainsKey(msg[i]))
{
list.Add(msg[i], new List<int>());
list[msg[i]].Add(i);
}
else
list[msg[i]].Add(i);
}
Simple = best. Without memory allocation.
public static IEnumerable<int> GetIndexOfEvery(string haystack, string needle)
{
int index;
int pos = 0;
string s = haystack;
while((index = s.IndexOf(needle)) != -1)
{
yield return index + pos;
pos = pos + index + 1;
s = haystack.Substring(pos);
}
}
I have the following code..
var strings = new[] {
"FD1","FD5","FD10","FD102","FD105","FD10","FD32","FD80", "FD31", "FD21", "FDnon"
};
strings = strings.Select(str => new
{
str,
num = int.Parse(String.Concat(str.Trim('F', 'D'))),
})
.OrderBy(x => x.num)
.Select(x => x.str)
.ToArray();
However this fails when it gets to "FDnon" as there are no numbers in it,
How do I get this to work with "FDnon" sorted at the top?
var result = strings.OrderBy(x =>
{
int y = int.MinValue;
int.TryParse(x.Substring(2), out y);
return y;
});
If you want custom ordering, supply your custom SortMethod
var sorted = strings
.OrderBy(SpecialSort)
.ToList();
public static int SpecialSort(string value)
{
int sortOrder = 0;
string numberPart = value.Trim('F', 'D');
int.TryParse(numberPart, out sortOrder);
return sortOrder;
}
Edit: Changed solution to account for the sorting of numbers in String.
If you want FDnon to be presented at the top you can use something like:
strings = strings.Select(str => new
{
str,
num = str=="FDnon" ? Int32.MaxValue : Int32.Parse(String.Concat(str.Trim('F', 'D')))
})
.OrderBy(x => x.num)
.Select(x => x.str)
.ToArray();
This code just skips FDnon conversion. If you want to allow other values you should be more specific on what are you going to accept.
You need a more sophisticated parse that converts FDnon into an integral value that will sort last (in this case Int32.MaxValue would do).
Something like:
var res = strings.Select(s => {
var numPart = s.Trim('F', 'D');
var i;
if (!Int32.TryParse(numPart, out i)) {
i = Int32.MaxValue;
}
return new {
str = s,
num = i
};
}.OrderBy …
If the strings always start with two letters, you could also use Substring(2). To check if there's a numeric part, you can use Enumerable.All(Char.IsDigit) (assumes that all chars are digits after the first two lewtters):
strings = strings.Select(str => new
{
str,
num = str.Substring(2).All(Char.IsDigit) ? int.Parse(str.Substring(2)) : int.MinValue
})
.OrderBy(x => x.num)
.Select(x => x.str)
.ToArray();
DEMO
I'm hoping to find a better way (maybe with a nice linq expression) to convert a string list like "41,42x,43" to a list of valid long's. The below code works, but just feels ugly.
string addressBookEntryIds = "41,42x,43";
var ids = addressBookEntryIds.Split(new[] {',', ';'}, StringSplitOptions.RemoveEmptyEntries);
var addressBookEntryIdList =new List<long>();
foreach (var rec in ids)
{
long val;
if (Int64.TryParse(rec, out val))
{
addressBookEntryIdList.Add(val);
}
}
string addressBookEntryIds = "41,42x,43";
Func<string, long?> safeParse = (s) => {
long val;
if (Int64.TryParse(s, out val))
{
return val;
}
return null;
};
var longs = (from s in addressBookEntryIds.Split(new[] {',', ';'}, StringSplitOptions.RemoveEmptyEntries)
let cand = safeParse(s)
where cand.HasValue
select cand.Value).ToList();
use regex
var list = Regex.Matches(#"41,42x,43", #"\d+").Cast<Match>().Select(x => Convert.ToInt64(x.Value)).ToList();
Here's another LINQ version:
String addressBookEntryIds = "41,42x,43";
Int64 val = 0;
addressBookEntryIds
.Split(new[] {',', ';'}, StringSplitOptions.RemoveEmptyEntries)
.Where(id => Int64.TryParse(id, out val))
.Select(id => val)
.ToList()
If you prefer a query expression, you can use:
from id in addressBookEntryIds.Split(new[] {',', ';'}, StringSplitOptions.RemoveEmptyEntries)
where Int64.TryParse(id, out val)
select val
Well, here's a LINQ version, but it's not really any less ugly!
string addressBookEntryIds = "41,42x,43";
var ids = addressBookEntryIds.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
Int64 converted; // Working value used within the select
IEnumerable<Int64> values = ids.Select(x => new
{
Success = Int64.TryParse(x, out converted),
Value = converted
}).Where(x => x.Success)
.Select(x => x.Value);
The difference between this solution and anderson's is that TryParse is only called once per entry.
Just a derivation of your code, quite redundant (uses TryParse and then Parse again), but I think it works:
addressBookEntryIds.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
.Where(id =>
{
long val;
return Int64.TryParse(id, out val);
})
.Select(id => Int64.Parse(id));