How to add numbers in a string separated by delimiter - c#

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();

Related

Looking for next match (integer) in list of strings

I have a problem finding the next integer match in a list of strings, there are some other aspects to consider:
single string contains non relevant trailing and leading chars
numbers are formatted "D6" example 000042
there are gaps in the numbers
the list is not sorted, but it could be if there is a fast way to ignore the leading chars
Example:
abc-000001.file
aaac-000002.file
ab-002010.file
abbc-00003.file
abbbc-00004.file
abcd-00008.file
abc-000010.file
x-902010.file
The user input is 7 => next matching string would be abcd-000008.file
My attempt is :
int userInput = 0;
int counter = 0;
string found = String.Empty;
bool run = true;
while (run)
{
for (int i = 0; i < strList.Count; i++)
{
if(strList[i].Contains((userInput + counter).ToString("D6")))
{
found = strList[i];
run = false;
break;
}
}
counter++;
}
It's bad because it's slow and it can turn into a infinite loop. But I really don't know how to do this (fast).
You can parse numbers from strings with Regex and created a sorted collection which you can search with Where clause:
var strings = new[] { "abc-000001.file", "x-000004.file"};
var regP = "\\d{6}"; // simplest option in my example, maybe something more complicated will be needed
var reg = new Regex(regP);
var collection = strings
.Select(s =>
{
var num = reg.Match(s).Captures.First().Value;
return new { num = int.Parse(num), str = s};
})
.OrderBy(arg => arg.num)
.ToList();
var userInput = 2;
var res = collection
.Where(arg => arg.num >= userInput)
.FirstOrDefault()?.str; // x-000004.file
P.S.
How 9002010, 0000010, 0002010 should be treated? Cause they have 7 characters. Is it [9002010, 10, 2010] or [900201, 1, 201]?
If you don't want regex, you can do something like that:
List<string> strings = new List<string>
{
"abc-000001.file",
"aaac-000002.file",
"ab-0002010.file",
"abbc-000003.file",
"abbbc-000004.file",
"abcd-000008.file"
};
int input = 7;
var converted = strings.Select(s => new { value = Int32.Parse(s.Split('-', '.')[1]), str = s })
.OrderBy(c => c.value);
string result = converted.FirstOrDefault(v => v.value >= input)?.str;
Console.WriteLine(result);

Retrieving Numeric value before a decimal in a string value

I am working on a routine in C#
I have a list of alphanumeric sheet numbers that I would like to retrieve the numbers before the decimal to use in my routine.
FP10.01-->10
M1.01-->1
PP8.01-->8
If possible, how can something like this be achieved as either a string or integer?
You could use a regex:
Regex r = new Regex("([0-9]+)[.]");
string s = "FP10.01";
var result = Convert.ToInt32(r.Match(s).Groups[1].ToString()); //10
string input = "FP10.01";
string[] _input = input.Split('.');
string num = find(_input[0]);
public string find(string input)
{
char[] _input = input.ToArray();
int number;
string result = null;
foreach (var item in _input)
{
if (int.TryParse(item.ToString(), out number) == true)
{
result = result + number;
}
}
return result;
}
To accumulate the resulting elements into a list, you can do something like:
List<string> myList = new List<string>(){ "FP10.01","M1.01", "PP8.01"};
List<int> resultSet =
myList.Select(e =>
Regex.Replace(e.Substring(0, e.IndexOf('.')), #"[^\d]", string.Empty))
.Select(int.Parse)
.ToList();
This will take each element in myList and in turn, take a substring of each element from index 0 until before the . and then replace all the non-numeric data with string.Empty and then finally parse the string element into an int and store it into a list.
another variant would be:
List<int> resultSet =
myList.Select(e => e.Substring(0, e.IndexOf('.')))
.Select(e => string.Join(string.Empty, e.Where(char.IsDigit)))
.Select(int.Parse)
.ToList();
or if you want the elements to be strings then you could do:
List<string> resultSet =
myList.Select(e => e.Substring(0, e.IndexOf('.')))
.Select(e => string.Join(string.Empty, e.Where(char.IsDigit)))
.ToList();
To retrieve a single element of type string then you can create a helper function as such:
public static string GetValueBeforeDot(string input){
return input.Substring(0, input.IndexOf('.'))
.Where(char.IsDigit)
.Aggregate(string.Empty, (e, a) => e + a);
}
To retrieve a single element of type int then the helper function should be:
public static int GetValueBeforeDot(string input){
return int.Parse(input.Substring(0, input.IndexOf('.'))
.Where(char.IsDigit)
.Aggregate(string.Empty, (e, a) => e + a));
}
This approach removes alphabet characters by replacing them with an empty string. Splitting on the '.' character will leave you with a two element array consisting of numbers at index 0 and after decimal values at index 1.
string input = "FP10.01";
var result = Regex.Replace(input, #"([A-Za-z]+)", string.Empty).Split('.');
var beforeDecimalNumbers = result[0]; // 10
var afterDecimalNumbers = result[1]; // 01

Find comma in a Textbox full of integers

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
}

How to get the indexes and reoccurrences of a specific character?

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);
}
}

Comparing strings with hyphen

I have some strings in a list
List<string> list = new List<string>{ "100-1", "100-11", "100-3", "100-20" }
I used following code to sort which is picked from this location
void Main()
{
string[] things= new string[] { "100-1", "100-11", "100-3", "100-20" };
foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
{
Console.WriteLine(thing);
}
}
public class SemiNumericComparer: IComparer<string>
{
public int Compare(string s1, string s2)
{
if (IsNumeric(s1) && IsNumeric(s2))
{
if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1;
if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1;
if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0;
}
if (IsNumeric(s1) && !IsNumeric(s2))
return -1;
if (!IsNumeric(s1) && IsNumeric(s2))
return 1;
return string.Compare(s1, s2, true);
}
public static bool IsNumeric(object value)
{
try {
int i = Convert.ToInt32(value.ToString());
return true;
}
catch (FormatException) {
return false;
}
}
}
My output is 100-1, 100-11, 100-20, 100-3
I believe it is taking - as decimal and comparing the values. Actually I was expecting the result to be
100-1, 100-3, 100-11, 100-20.
I just wanted to know on what basis it is actually performing sort. Any help is appreciated. Even I expect it to treat 100-2 and 100-20 differently.
Just on the fly, I have seen in Infragistic control grid that sorting in it produces the same result as I was expecting here to be.
I have many other string values in the list, some are integers, doubles and so on. Hyphen is just a case mentioned here.
var sorted = things.Select(s => s.Split('-'))
.OrderBy(x => double.Parse(x[0]))
.ThenBy(x => double.Parse(x[1]))
.Select(x=>String.Join("-",x))
.ToList();
This should work as expected:
string[] things= new string[] { "100-1", "100-11", "100-3", "100-20" };
IEnumerable<string> ordered = things
.Select(s => new
{
str = s,
firstPart = s.Split('-').ElementAtOrDefault(0),
secondPart = s.Split('-').ElementAtOrDefault(1)
})
.OrderBy(x => int.Parse(x.firstPart))
.ThenBy(x => int.Parse(x.firstPart))
.Select(x => x.str);
foreach (string s in ordered)
Console.WriteLine(s);
Although it assumes that your data is strict, otherwise you're open for exceptions, f.e at int.Parse(x.firstPart).
Demo: http://ideone.com/UJ5Yt4
If you want to sort the items by the 2nd number (after hyphen), You need to parse the string to a number then order by using it. you can try:
string[] things = new string[] { "100-1", "100-11", "100-3", "100-20" };
var test = things.OrderBy(r => int.Parse(r.Split('-')[1])).ToArray();
The reason your current code is not working is probably due to the fact that it can't parse the string 100- to an integer value and your function IsNumeric is returning false.

Categories

Resources