How to separate string and save in the array in asp.net - c#

I have got column in db which saves the string as 1,2,3,4,5
I want to separate the string to 1 2 3 4 5 and save each number in the array , for instance the array should be like int [] numbers , int[0] = 1 , int[1] = 2 ......

Looks like you want:
int[] array = text.Split(',')
.Select(x => int.Parse(x, CultureInfo.InvariantCulture))
.ToArray();
Obviously this will go bang if any of the split results is not a parsable integer.
(You may also want to use a List<int> instead of an array, as a generally more flexible collection type.)
EDIT: Short but complete demo program:
using System;
using System.Globalization;
using System.Linq;
public class Test
{
static void Main()
{
string eventIds = "1,2,3";
int[] array =
eventIds.Split(',')
.Select(x => int.Parse(x, CultureInfo.InvariantCulture))
.ToArray();
foreach (int id in array)
{
Console.WriteLine(id);
}
}
}

here is code
Dim str as String = "1,2,3,4,5"
dim objstr() as String = str.split(",")
here split return array.

Here's a "safer" version of John's excellent code snippet that will deal with values that cannot be parsed as int by adding them as 0:
int temp;
int[] array = text.Split(',')
.Select(x => int.TryParse(x, out temp) ? temp : 0)
.ToArray();
If you want to be totally safe and discard any values that cannot be converted to an integer then you could use a function like this:
private static int[] ConvertTextToIntArray(string text)
{
var integerList = new List<int>();
var values = text.Split(',');
int temp;
foreach (var value in values)
{
if (int.TryParse(value, out temp))
{
integerList.Add(temp);
}
}
return integerList.ToArray();
}

Related

Linq return 2D array with index from string splitting

I have a folder with multiple files with format NameIndex.Index. I need a 2D array returned with Linq, where Name is my string and the two indices (both only 1 char) are the 2D array indices.
Example: Head4.2 will be in my returned array on the [4,2] position.
File[,] files = arrayWithAllFiles.Select(f => f.name.StartsWith(partName))
. // dont know how to continue
/*
result would look like, where the element is the File (not it's name):
| Head0.0 Head0.1 Head0.2 ... |
| Head1.0 Head1.1 Head1.2 ... |
*/
PS: could it be also done to check for indices bigger than 9?
You can use Regex to parse the file names, that way you don't have to worry about the numbers being bigger than 9. The numbers can have more than one digit.
For example,
using System.Text.RegularExpressions;
/*
Pattern below means - one or more non-digit characters, then one or more digits,
then a period, then one or more digits. Each segment inside the parentheses will be one
item in the split array.
*/
string pattern = #"^(\D+)(\d+)\.(\d+)$";
string name = "Head12.34";
var words = Regex.Split(name, pattern);
// Now words is an array of strings - ["Head", "12", "34"]
So for your example you could try:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
string pattern = #"^(\D+)(\d+)\.(\d+)$";
var indices = files.Select(f =>
Regex.Split(f.name, pattern).Skip(1).Select(w => System.Convert.ToInt32(w)).ToArray()).ToArray();
// Getting the max indices in each direction. This decides the dimensions of the array.
int iMax = indices.Select(p => p[0]).Max();
int jMax = indices.Select(p => p[1]).Max();
var pairs = Enumerable.Zip(indices, files, (index, file) => (index, file));
File[,] files = new File[iMax + 1, jMax + 1];
foreach (var pair in pairs){
files[pair.index[0], pair.index[1]] = pair.file;
}
I'm not much of a regex fan, thats why I suggest the following solution, assuming your input is valid:
private static (string name, int x, int y) ParseText(string text)
{
var splitIndex = text.IndexOf(text.First(x => x >= '0' && x <= '9'));
var name = text.Substring(0, splitIndex);
var position = text.Substring(splitIndex).Split('.').Select(int.Parse).ToArray();
return (name, position[0], position[1]);
}
private static string[,] Create2DArray((string name, int x, int y)[] items)
{
var array = new string[items.Max(i => i.x) + 1, items.Max(i => i.y) + 1];
foreach (var item in items)
array[item.x, item.y] = item.name;
return array;
}
Then you can call these functions like this:
var files = new[] { "head1.0", "head4.1", "head2.3" };
var arr = Create2DArray(files.Select(ParseText).ToArray());

Faster way of finding all indices of specific string in an array

Below code is used to find all indices of a string that might occur only once in an array but the code isn't very fast. Does somebody know a faster and more efficient way to find unique strings in an array?
using System;
using System.Collections.Generic;
using System.Linq;
public static class EM
{
// Extension method, using Linq to find indices.
public static int[] FindAllIndicesOf<T>(this IEnumerable<T> values, T val)
{
return values.Select((b,i) => Equals(b, val) ? i : -1).Where(i => i != -1).ToArray();
}
}
public class Program
{
public static string FindFirstUniqueName(string[] names)
{
var results = new List<string>();
for (var i = 0; i < names.Length; i++)
{
var matchedIndices = names.FindAllIndicesOf(names[i]);
if (matchedIndices.Length == 1)
{
results.Add(names[matchedIndices[0]]);
break;
}
}
return results.Count > 0 ? results[0] : null;
}
public static void Main(string[] args)
{
Console.WriteLine("Found: " + FindFirstUniqueName(new[]
{
"James",
"Bill",
"Helen",
"Bill",
"Helen",
"Giles",
"James",
}
));
}
}
Your solution has O(n^2) complexity. You can improve it to O(n) by using Hash-Map.
Consider a Hash-Map with which in each name has it number of recurrences in your original list. Now all you have to do is check all key in the dictionary (aka hash-map) and return all that equal to 1. Notice that check all key in this dictionary is less then o(n) because it can not hold more then n names.
To implement this dictionary in C# you do as follow:
List<string> stuff = new List<string>();
var groups = stuff.GroupBy(s => s).Select(
s => new { Stuff = s.Key, Count = s.Count() });
var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);
Taken from here or as suggested by juharr
O(n) is the minimum require as you will have to go over all names at least once.

How to parse a text file with alternating lines of names and lists of integers?

I need to read a file and put that data inside to different arrays.
My .txt file looks like:
w1;
1 2 3
w2;
3 4 5
w3;
4 5 6
I tried something like the following:
int[] w1 = new int [3];
int[] w2 = new int [3];
int[] w3 = new int [3];
string v = "w1:|w2:|w3:";
foreach (string line in File.ReadAllLines(#"D:\\Data.txt"))
{
string[] parts = Regex.Split(line, v);
I got that string but I have no idea how to cut every element of it to arrays showed above.
Rather than parsing the file and putting the arrays into three hardcoded variables corresponding to hardcoded names w1, w2 and w3, I would remove the hardcoding and parse the file into a Dictionary<string, int[]> like so:
public static class DataFileExtensions
{
public static Dictionary<string, int[]> ParseDataFile(string fileName)
{
var separators = new [] { ' ' };
var query = from pair in File.ReadLines(fileName).Chunk(2)
let key = pair[0].TrimEnd(';')
let value = (pair.Count < 2 ? "" : pair[1]).Split(separators, StringSplitOptions.RemoveEmptyEntries).Select(s => int.Parse(s, NumberFormatInfo.InvariantInfo)).ToArray()
select new { key, value };
return query.ToDictionary(p => p.key, p => p.value);
}
}
public static class EnumerableExtensions
{
// Adapted from the answer to "Split List into Sublists with LINQ" by casperOne
// https://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq/
// https://stackoverflow.com/a/419058
// https://stackoverflow.com/users/50776/casperone
public static IEnumerable<List<T>> Chunk<T>(this IEnumerable<T> enumerable, int groupSize)
{
// The list to return.
List<T> list = new List<T>(groupSize);
// Cycle through all of the items.
foreach (T item in enumerable)
{
// Add the item.
list.Add(item);
// If the list has the number of elements, return that.
if (list.Count == groupSize)
{
// Return the list.
yield return list;
// Set the list to a new list.
list = new List<T>(groupSize);
}
}
// Return the remainder if there is any,
if (list.Count != 0)
{
// Return the list.
yield return list;
}
}
}
And you would use it as follows:
var dictionary = DataFileExtensions.ParseDataFile(fileName);
Console.WriteLine("Result of parsing {0}, encountered {1} data arrays:", fileName, dictionary.Count);
foreach (var pair in dictionary)
{
var name = pair.Key;
var data = pair.Value;
Console.WriteLine(" Data row name = {0}, values = [{1}]", name, string.Join(",", data));
}
Which outputs:
Result of parsing Question49341548.txt, encountered 3 data arrays:
Data row name = w1, values = [1,2,3]
Data row name = w2, values = [3,4,5]
Data row name = w3, values = [4,5,6]
Notes:
I parse the integer values using NumberFormatInfo.InvariantInfo to ensure consistency of parsing in all locales.
I break the lines of the file into chunks of two by using a lightly modified version of the method from this answer to Split List into Sublists with LINQ by casperOne.
After breaking the file into chunks of pairs of lines, I trim the ; from the first line in each pair and use that as the dictionary key. The second line in each pair gets parsed into an array of integer values.
If the names w1, w2 and so on are not unique, you could deserialize instead into a Lookup<string, int []> by replacing ToDictionary() with ToLookup().
Rather than loading the entire file into memory upfront using File.ReadAllLines(), I enumerate though it sequentially using File.ReadLines(). This should reduce memory usage without any additional complexity.
Sample working .Net fiddle.
Your RegEx doesn't actually do anything, you already have an array with each line separated. What you want to do is just ignore the lines that aren't data:
var lines = File.ReadAllLines(#"D:\\Data.txt");
for (int i = 1; i < lines.Length; i += 2) // i.e indexes 1, 3 and 5
{
string[] numbers = lines[i].Split(' ');
}
Or, you could just assign given that you know the order:
w1 = lines[1].Split(' ');
w2 = lines[3].Split(' ');
w3 = lines[5].Split(' ');

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

C#: Adding data to dictionary

I have a list like
List<string> TempList = new List<string> { "[66,X,X]", "[67,X,2]", "[x,x,x]" };
I need to add data to the dictionary from the above list
Dictionary<int, int> Dict = new Dictionary<int, int>();
so the Dict should contain
Key --> 66 value --> 67
i need to take 66(first value) from first string([66,X,X]) and 67(first value) from second string( [67,X,X]) and add it as a key value pair into the dictionary.
Now i'm following string replacing and looping methodology to do this .
Is there any way to do this in LINQ or Regular expression.
After your comment that you're starting from a list of lists, I understood what you were after. I'm reusing Jaroslav's 'GetNumber' function here. Wrote my sample with array of array of string, but should work just the same. The code below will throw if you have duplicate keys, which I presume is what you want if you're using a dictionary.
var input = new []
{
new [] { "[66,X,X]", "[67,X,2]", "[x,x,x]" },
new [] { "[5,X,X]", "[8,X,2]", "[x,x,x]" }
};
var query = from l in input
select new
{
Key = GetNumber(l.ElementAt(0)),
Value = GetNumber(l.ElementAt(1))
};
var dictionary = query.ToDictionary(x => x.Key, x => x.Value);
Here is an example using both string.Split() and a Regex:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<string> data = new List<string>() { "[66,X,X]", "[67,X,2]", "[x,x,x]" };
addToDict(data);
Console.ReadKey();
}
private static void addToDict(List<string> items)
{
string key = items[0].Split('[', ',')[1];
string val = items[1].Split('[', ',')[1];
string pattern = #"(?:^\[)(\d+)";
Match m = Regex.Match(items[0], pattern);
key = m.Groups[1].Value;
m = Regex.Match(items[1], pattern);
val = m.Groups[1].Value;
_dict.Add(key, val);
}
static Dictionary<string, string> _dict = new Dictionary<string, string>();
}
}
i suspect that your example is quite contrived though, so there may be a better solution especially if you need to process large numbers of strings into key/value pairs (i deliberately hardcoded index values because your example was quite simple and i didn't want to over complicate the answer). If the input data is consistent in format then you can make assumptions like using fixed indexes, but if there is a possibility of some variance then there may need to be more code to check the validity of it.
You can use a regular expression to extract the value from each item in the list, and if you want, use LINQ to select out two lists and zip them together (in C# 4.0):
var regex = new Regex(#"\d+");
var allValues = TempList.Select(x =>int.Parse(regex.Match(x).Value));
var dictKeys = allValues.Where((x,index)=> index % 2 == 0); //even-numbered
var dictValues = allValues.Where((x,index)=> index % 2 > 0); //odd numbered
var dict = dictKeys.Zip(dictValues, (key,value) => new{key,value})
.ToDictionary(x=>x.key,x=>x.value);
If you're using C# 3.5, you can use Eric Lippert's implementation of Zip().
IF I understand correctly: you want to create linked nodes like 66 -> 67, 67 -> 68, ... n -> n+1?
I would not use LINQ:
private static int GetNumber(string s)
{
int endPos = s.IndexOf(',');
return Int32.Parse(s.Substring(1, endPos-1));
}
And in code:
int first, second;
for (int i = 1; i < TempList.Count; i++)
{
first = GetNumber(TempList[i - 1]);
second = GetNumber(TempList[i]);
Dict.Add(first, second);
}
You should also perform checking, etc.
The sample assumes a list with at least 2 items.
List<List<string>> source = GetSource();
Dictionary<int, int> result = source.ToDictionary(
tempList => GetNumber(tempList[0]),
tempList => GetNumber(tempList[1])
);

Categories

Resources