I only found a way to do it the opposite way round: create a comma separated string from an int list or array, but not on how to convert input like string str = "1,2,3,4,5"; to an array or list of ints.
Here is my implementation (inspired by this post by Eric Lippert):
public static IEnumerable<int> StringToIntList(string str)
{
if (String.IsNullOrEmpty(str))
{
yield break;
}
var chunks = str.Split(',').AsEnumerable();
using (var rator = chunks.GetEnumerator())
{
while (rator.MoveNext())
{
int i = 0;
if (Int32.TryParse(rator.Current, out i))
{
yield return i;
}
else
{
continue;
}
}
}
}
Do you think this is a good approach or is there a more easy, maybe even built in way?
EDIT: Sorry for any confusion, but the method needs to handle invalid input like "1,2,,,3" or "###, 5," etc. by skipping it.
You should use a foreach loop, like this:
public static IEnumerable<int> StringToIntList(string str) {
if (String.IsNullOrEmpty(str))
yield break;
foreach(var s in str.Split(',')) {
int num;
if (int.TryParse(s, out num))
yield return num;
}
}
Note that like your original post, this will ignore numbers that couldn't be parsed.
If you want to throw an exception if a number couldn't be parsed, you can do it much more simply using LINQ:
return (str ?? "").Split(',').Select<string, int>(int.Parse);
If you don't want to have the current error handling behaviour, it's really easy:
return text.Split(',').Select(x => int.Parse(x));
Otherwise, I'd use an extra helper method (as seen this morning!):
public static int? TryParseInt32(string text)
{
int value;
return int.TryParse(text, out value) ? value : (int?) null;
}
and:
return text.Split(',').Select<string, int?>(TryParseInt32)
.Where(x => x.HasValue)
.Select(x => x.Value);
or if you don't want to use the method group conversion:
return text.Split(',').Select(t => t.TryParseInt32(t)
.Where(x => x.HasValue)
.Select(x => x.Value);
or in query expression form:
return from t in text.Split(',')
select TryParseInt32(t) into x
where x.HasValue
select x.Value;
Without using a lambda function and for valid inputs only, I think it's clearer to do this:
Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);
--EDIT-- It looks like I took his question heading too literally - he was asking for an array of ints rather than a List --EDIT ENDS--
Yet another helper method...
private static int[] StringToIntArray(string myNumbers)
{
List<int> myIntegers = new List<int>();
Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
{
int currentInt;
if (Int32.TryParse(s, out currentInt))
myIntegers.Add(currentInt);
});
return myIntegers.ToArray();
}
quick test code for it, too...
static void Main(string[] args)
{
string myNumbers = "1,2,3,4,5";
int[] myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 15.
myNumbers = "1,2,3,4,5,6,bad";
myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 21
Console.ReadLine();
}
Let us assume that you will be reading the string from the console. Import System.Linq and try this one:
int[] input = Console.ReadLine()
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
This has been asked before. .Net has a built-in ConvertAll function for converting between an array of one type to an array of another type. You can combine this with Split to separate the string to an array of strings
Example function:
static int[] ToIntArray(this string value, char separator)
{
return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
}
Taken from here
This is for longs, but you can modify it easily to work with ints.
private static long[] ConvertStringArrayToLongArray(string str)
{
return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}
I don't see why taking out the enumerator explicitly offers you any advantage over using a foreach. There's also no need to call AsEnumerable on chunks.
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
String line;
String[] lineVector;
int n,m,i,j;
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
lineVector = line.split(",");
//enter the size of the array
n=Integer.parseInt(lineVector[0]);
m=Integer.parseInt(lineVector[1]);
int arr[][]= new int[n][m];
//enter the array here
System.out.println("Enter the array:");
for(i=0;i<n;i++)
{
line = sc.nextLine();
lineVector = line.split(",");
for(j=0;j<m;j++)
{
arr[i][j] = Integer.parseInt(lineVector[j]);
}
}
sc.close();
}
}
On the first line enter the size of the array separated by a comma. Then enter the values in the array separated by a comma.The result is stored in the array arr.
e.g
input:
2,3
1,2,3
2,4,6
will store values as
arr = {{1,2,3},{2,4,6}};
Related
I'm trying to take objects out of an object list to an int list. If the object list's value contains a string than I want to convert it to an int. the error that I'm getting is "cannot convert from 'object' to 'System.ReadOnlySpan'. I've tried looking up examples and information about lists made of objects but couldn't find anything.
I'm also at a loss as to what to do with the 'else' part of the code.
public class ListFilterer
{
public static IEnumerable(int) GetIntegersFromList(List(object) listOfItems)
{
List<int> Integers = new List<int>();
foreach (var value in listOfItems)
{
int number = 0;
bool success = Int32.TryParse(value, out number);
if (success)
{
Integers.Add(number);
}
else
{
Integers.Add(number);
}
}
return Integers;
}
}
It'll probably work out if you TryParse value.ToString() instead, if you're looking for anything that might look like an int and can be converted to an int. If you only want things that actually are ints, something like if(value is int number) should work if your c# version is recent. If it's older you may have to if(value is int) and then cast the value inside the if
Your code can be simplified to:
foreach(...){
int.TryParse(value.ToString(), out var n);
integers.Add(n);
}
Or
foreach(...){
if(value is int)
integers.Add((int)value);
else
integers.Add(0);
}
You could simply use:
var ints = listOfItems
.Select(o => { int.TryParse(o.ToString(), out int num); return num;} )
.ToList();
This will work as you wish, as if conversion fails num is 0 by default.
If Try Parse fails number is automatically 0 so you can directly write this
Int32.TryParse(value, out int number)
Integers.Add(number);
Maybe you can find the better way
var intList = objs.ConvertAll(delegate (object obj) { return (int)obj; });
So i have this C# code:
static void Main(string[] args)
{
string #string = "- hello dude! - oh hell yeah hey what's up guy";
Console.WriteLine(String.Join(".", #string.GetSubstringsIndexes("he")));
Console.Read();
}
partial class that adds an extension "GetSubstringsIndexes" method:
partial class StringExtension
{
public static int[] GetSubstringsIndexes(this string #string, string substring)
{
List<int> indexes = new List<int>(#string.Length / substring.Length);
int result = #string.IndexOf(substring, 0);
while (result >= 0)
{
indexes.Add(result);
result = #string.IndexOf(substring, result + substring.Length);
}
return indexes.ToArray();
}
}
What i would want it to be like, is a lambda expression in the parameters brackets of a String.Join method instead of calling a function i wrote.
I mean, i would just want not to write this function and THEN call it, but to write a lambda expression to use only once!
Example of how i would want it to look like:
static void Main(string[] args)
{
string #string = "- hello dude! - oh hell yeah hey what's up guy";
Console.WriteLine(String.Join(".", () => {List<int> ind = new List<int>()..... AND SO ON...} ));
Console.Read();
}
Well, actually, I've just realized (while writing this question) that for this kind of a situation it is unnecessary, because my GetSubStringsIndexes method is too big. But imagine if it were a short one.
Just tell me whether or not it is possible to do something like that, and if it is possible, please, tell me how!
Edit:
I've done it and that's how it looks like:
Console.WriteLine(String.Join(".", ((Func<int[]>)
( () =>
{
List<int> indx = new List<int>();
int res = #string.IndexOf("he", 0);
while (res >= 0)
{
indx.Add(res);
res = #string.IndexOf("he", res + "he".Length);
}
return indx.ToArray();
}
))()));
Your "improvement" in the question works. Here is a more concise way of doing that with a helper function that you need to define only once:
static void Execute<TReturn>(Func<TReturn> func) => func();
Then:
Console.WriteLine(Execute(() => { /* any code here */ }));
This infers the delegate type automatically and calls the delegate. This removes a lot of clutter.
In general I'd advise against this style. Use multiple lines of code instead.
What you want isn't possible, as String.join() doesn't accept a Func<int[]> or an Expression<Func<int[]>>.
You could use a local function and call that, if you don't want to write an extension method.
static void Main(string[] args)
{
string #string = "- hello dude! - oh hell yeah hey what's up guy";
Console.WriteLine(String.Join(".", GetIndexes('he'));
Console.Read();
int[] GetIndexes(string substring) {
var indexes = new List<int>();
// compute indexes as desired. #string is available here.
return indexes.ToArray();
}
}
One way to do it would be to use a Select statement where you capture both the character being examined and it's index in the string (using the syntax: Select((item, index) => ...), and then, if the substring exists at that index, return the index, otherwise return -1 (from the Select statement), and then follow that up with a Where clause to remove any -1 results.
The code is a little long because we also have to be sure that we aren't too close to the end of the string before we check the substring (which results in another ternary condition that returns -1).
I'm sure this can be improved, but it's a start:
string #string = "- hello dude! - oh hell yeah hey what's up guy";
var subString = "he";
Console.WriteLine(string.Join(".", #string.Select((chr, index) =>
index + subString.Length < #string.Length
? #string.Substring(index, subString.Length) == subString
? index
: -1
: -1)
.Where(result => result > -1)));
In case that's too hard to read (due to the multiple ?: ternary expressions), here it is with comments before each line:
// For each character in the string, grab the character and it's index
Console.WriteLine(string.Join(".", #string.Select((chr, index) =>
// If we're not too close to the end of the string
index + subString.Length < #string.Length
// And the substring exists at this index
? #string.Substring(index, subString.Length) == subString
// Return this index
? index
// Substring not found here; return -1
: -1
// We're too close to end; return -1
: -1)
// Return only the indexes where the substring was found
.Where(result => result > -1)));
The final result:
Console.WriteLine(String.Join(".", ((Func<int[]>)
( () =>
{
List<int> indx = new List<int>();
int res = #string.IndexOf("he", 0);
while (res >= 0)
{
indx.Add(res);
res = #string.IndexOf("he", res + "he".Length);
}
return indx.ToArray();
}
))()));
I've got the following method I created which works fine if there actually is the delimiter in question. I want to keep this out of LINQ for now...
e.g.
If I pass in the string "123;322;323" it works great.
But if I only pass in one string value without the delimiter such as "123" it obviously is not going to split it since there is no delimiter. I am just trying to figure out the best way to check and account for this and be able to spit out that one value back in the list
public static List<int> StringToList(string stringToSplit, char splitDelimiter)
{
List<int> list = new List<int>();
if (string.IsNullOrEmpty(stringToSplit))
return list;
string[] values = stringToSplit.Split(splitDelimiter);
if (values.Length < 1)
return list;
foreach (string s in values)
{
int i;
if (Int32.TryParse(s, out i))
list.Add(i);
}
return list;
}
UPDATED: This is what I came up with that seems to work but sure is long
public static List<int> StringToList(string stringToSplit, char splitDelimiter)
{
List<int> list = new IntList();
if (string.IsNullOrEmpty(stringToSplit))
return list;
if (stringToSplit.Contains(splitDelimiter.ToString()))
{
string[] values = stringToSplit.Split(splitDelimiter);
if (values.Length <= 1)
return list;
foreach (string s in values)
{
int i;
if (Int32.TryParse(s, out i))
list.Add(i);
}
}
else if (stringToSplit.Length > 0)
{
int i;
if(Int32.TryParse(stringToSplit, out i))
list.Add(i);
}
return list;
}
Change this condition:
if (values.Length <= 1)
return list;
To:
if (values.Length <= 0)
return list;
This works because String.Split will return the original string if it can't find the delimiter:
// stringToSplit does not contain the splitDelimiter
string[] values = stringToSplit.Split(splitDelimiter);
// values is a string array containing one value - stringToSplit
There are a LOT of unnecessary checks for conditions that don't matter to the core logic of the method.
public static List<int> StringToList(string stringToSplit, char splitDelimiter)
{
List<int> list = new IntList();
if (string.IsNullOrEmpty(stringToSplit))
return list;
//this if is not necessary. As others have said, Split will return a string[1] with the original string if no delimiter is found
if (stringToSplit.Contains(splitDelimiter.ToString()))
{
string[] values = stringToSplit.Split(splitDelimiter);
//why check this? if there are no values, the foreach will do nothing and fall through to a return anyway.
if (values.Length <= 1)
return list;
foreach (string s in values)
{
int i;
if (Int32.TryParse(s, out i))
list.Add(i);
}
}
//again, this is rendered redundant due to previous comments
else if (stringToSplit.Length > 0)
{
int i;
if(Int32.TryParse(stringToSplit, out i))
list.Add(i);
}
return list;
}
Try this. You hopefully have some unit tests calling this method to make sure it works...right?
public static List<int> StringToList(string stringToSplit, char splitDelimiter)
{
List<int> list = new IntList();
if (string.IsNullOrEmpty(stringToSplit))
return list;
foreach(var s in stringToSplit.Split(splitDelimiter))
{
int i;
if(int.TryParse(s, out i))
list.Add(i);
}
return list;
}
Personally, I haven't tried out your code, but it looks functional. The Split method should return an array with one element.
Since you say it's not, I believe you, and I would add this to the top of your method:
if (!stringToSplit.Contains(splitDelimiter))
{
int i;
if (Int32.TryParse(stringToSplit, out i))
list.Add(i);
return list;
}
You don't need to account for that situation, as string.Split() returns an array with a single element when no delimiter is found:
If this instance does not contain any of the strings in separator, the returned array consists of a single element that contains this instance.
See msdn at "Remarks"
Might I suggest an extension method to help you in cases like this in general?
The idea would be to yield return all results from a collection of strings that can be parsed to a specified type.
First you'd need a delegate to match the signature of your standard TryParse method:
public delegate bool Parser<T>(string input, out T value);
Then you can write an extension method that takes an instance of this delegate type and enumerates over a collection of strings, parsing everywhere it can:
// Notice: extension methods must belong to a class marked static.
public static class EnumerableParser
{
// modified code to prevent horizontal overflow
public static IEnumerable<T> ParseAll<T>
(this IEnumerable<string> strings, Parser<T> parser)
{
foreach (string str in strings)
{
T value;
if (parser(str, out value))
yield return value;
}
}
}
Now your StringToList method becomes trivial to implement:
public List<int> StringToList(string stringToSplit, char delimiter)
{
// Notice: since string.Split returns a string[], and string[] implements
// IEnumerable<string>, so the ParseAll extension method can be called on it.
return stringToSplit.Split(delimiter).ParseAll<int>(int.TryParse).ToList();
}
A shorter implementation you might consider.
public static List<int> StringToList(string stringToSplit, char splitDelimiter)
{
int i;
return stringToSplit.Split(splitDelimiter)
.Where(str => int.TryParse(str, out i))
.Select(str => int.Parse(str))
.ToList();
}
Either it must have a delimiter or, it part must have a fixed length or, the string must follow a pattern for repeat behavior.
I only found a way to do it the opposite way round: create a comma separated string from an int list or array, but not on how to convert input like string str = "1,2,3,4,5"; to an array or list of ints.
Here is my implementation (inspired by this post by Eric Lippert):
public static IEnumerable<int> StringToIntList(string str)
{
if (String.IsNullOrEmpty(str))
{
yield break;
}
var chunks = str.Split(',').AsEnumerable();
using (var rator = chunks.GetEnumerator())
{
while (rator.MoveNext())
{
int i = 0;
if (Int32.TryParse(rator.Current, out i))
{
yield return i;
}
else
{
continue;
}
}
}
}
Do you think this is a good approach or is there a more easy, maybe even built in way?
EDIT: Sorry for any confusion, but the method needs to handle invalid input like "1,2,,,3" or "###, 5," etc. by skipping it.
You should use a foreach loop, like this:
public static IEnumerable<int> StringToIntList(string str) {
if (String.IsNullOrEmpty(str))
yield break;
foreach(var s in str.Split(',')) {
int num;
if (int.TryParse(s, out num))
yield return num;
}
}
Note that like your original post, this will ignore numbers that couldn't be parsed.
If you want to throw an exception if a number couldn't be parsed, you can do it much more simply using LINQ:
return (str ?? "").Split(',').Select<string, int>(int.Parse);
If you don't want to have the current error handling behaviour, it's really easy:
return text.Split(',').Select(x => int.Parse(x));
Otherwise, I'd use an extra helper method (as seen this morning!):
public static int? TryParseInt32(string text)
{
int value;
return int.TryParse(text, out value) ? value : (int?) null;
}
and:
return text.Split(',').Select<string, int?>(TryParseInt32)
.Where(x => x.HasValue)
.Select(x => x.Value);
or if you don't want to use the method group conversion:
return text.Split(',').Select(t => t.TryParseInt32(t)
.Where(x => x.HasValue)
.Select(x => x.Value);
or in query expression form:
return from t in text.Split(',')
select TryParseInt32(t) into x
where x.HasValue
select x.Value;
Without using a lambda function and for valid inputs only, I think it's clearer to do this:
Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);
--EDIT-- It looks like I took his question heading too literally - he was asking for an array of ints rather than a List --EDIT ENDS--
Yet another helper method...
private static int[] StringToIntArray(string myNumbers)
{
List<int> myIntegers = new List<int>();
Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
{
int currentInt;
if (Int32.TryParse(s, out currentInt))
myIntegers.Add(currentInt);
});
return myIntegers.ToArray();
}
quick test code for it, too...
static void Main(string[] args)
{
string myNumbers = "1,2,3,4,5";
int[] myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 15.
myNumbers = "1,2,3,4,5,6,bad";
myArray = StringToIntArray(myNumbers);
Console.WriteLine(myArray.Sum().ToString()); // sum is 21
Console.ReadLine();
}
Let us assume that you will be reading the string from the console. Import System.Linq and try this one:
int[] input = Console.ReadLine()
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
This has been asked before. .Net has a built-in ConvertAll function for converting between an array of one type to an array of another type. You can combine this with Split to separate the string to an array of strings
Example function:
static int[] ToIntArray(this string value, char separator)
{
return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
}
Taken from here
This is for longs, but you can modify it easily to work with ints.
private static long[] ConvertStringArrayToLongArray(string str)
{
return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}
I don't see why taking out the enumerator explicitly offers you any advantage over using a foreach. There's also no need to call AsEnumerable on chunks.
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
String line;
String[] lineVector;
int n,m,i,j;
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
lineVector = line.split(",");
//enter the size of the array
n=Integer.parseInt(lineVector[0]);
m=Integer.parseInt(lineVector[1]);
int arr[][]= new int[n][m];
//enter the array here
System.out.println("Enter the array:");
for(i=0;i<n;i++)
{
line = sc.nextLine();
lineVector = line.split(",");
for(j=0;j<m;j++)
{
arr[i][j] = Integer.parseInt(lineVector[j]);
}
}
sc.close();
}
}
On the first line enter the size of the array separated by a comma. Then enter the values in the array separated by a comma.The result is stored in the array arr.
e.g
input:
2,3
1,2,3
2,4,6
will store values as
arr = {{1,2,3},{2,4,6}};
I need to search a string in the string array. I dont want to use any for looping in it
string [] arr = {"One","Two","Three"};
string theString = "One"
I need to check whether theString variable is present in arr.
Well, something is going to have to look, and looping is more efficient than recursion (since tail-end recursion isn't fully implemented)... so if you just don't want to loop yourself, then either of:
bool has = arr.Contains(var); // .NET 3.5
or
bool has = Array.IndexOf(arr, var) >= 0;
For info: avoid names like var - this is a keyword in C# 3.0.
Every method, mentioned earlier does looping either internally or externally, so it is not really important how to implement it. Here another example of finding all references of target string
string [] arr = {"One","Two","Three"};
var target = "One";
var results = Array.FindAll(arr, s => s.Equals(target));
Does it have to be a string[] ? A List<String> would give you what you need.
List<String> testing = new List<String>();
testing.Add("One");
testing.Add("Two");
testing.Add("Three");
testing.Add("Mouse");
bool inList = testing.Contains("Mouse");
bool exists = arr.Contains("One");
I think it is better to use Array.Exists than Array.FindAll.
Its pretty simple. I always use this code to search string from a string array
string[] stringArray = { "text1", "text2", "text3", "text4" };
string value = "text3";
int pos = Array.IndexOf(stringArray, value);
if (pos > -1)
{
return true;
}
else
{
return false;
}
If the array is sorted, you can use BinarySearch. This is a O(log n) operation, so it is faster as looping. If you need to apply multiple searches and speed is a concern, you could sort it (or a copy) before using it.
Each class implementing IList has a method Contains(Object value). And so does System.Array.
Why the prohibition "I don't want to use any looping"? That's the most obvious solution. When given the chance to be obvious, take it!
Note that calls like arr.Contains(...) are still going to loop, it just won't be you who has written the loop.
Have you considered an alternate representation that's more amenable to searching?
A good Set implementation would perform well. (HashSet, TreeSet or the local equivalent).
If you can be sure that arr is sorted, you could use binary search (which would need to recurse or loop, but not as often as a straight linear search).
You can use Find method of Array type. From .NET 3.5 and higher.
public static T Find<T>(
T[] array,
Predicate<T> match
)
Here is some examples:
// we search an array of strings for a name containing the letter “a”:
static void Main()
{
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, ContainsA);
Console.WriteLine (match); // Jack
}
static bool ContainsA (string name) { return name.Contains ("a"); }
Here’s the same code shortened with an anonymous method:
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, delegate (string name)
{ return name.Contains ("a"); } ); // Jack
A lambda expression shortens it further:
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, n => n.Contains ("a")); // Jack
At first shot, I could come up with something like this (but it's pseudo code and assuming you cannot use any .NET built-in libaries). Might require a bit of tweaking and re-thinking, but should be good enough for a head-start, maybe?
int findString(String var, String[] stringArray, int currentIndex, int stringMaxIndex)
{
if currentIndex > stringMaxIndex
return (-stringMaxIndex-1);
else if var==arr[currentIndex] //or use any string comparison op or function
return 0;
else
return findString(var, stringArray, currentIndex++, stringMaxIndex) + 1 ;
}
//calling code
int index = findString(var, arr, 0, getMaxIndex(arr));
if index == -1 printOnScreen("Not found");
else printOnScreen("Found on index: " + index);
In C#, if you can use an ArrayList, you can use the Contains method, which returns a boolean:
if MyArrayList.Contains("One")
You can check the element existence by
arr.Any(x => x == "One")
it is old one ,but this is the way i do it ,
enter code herevar result = Array.Find(names, element => element == "One");
I'm surprised that no one suggested using Array.IndexOf Method.
Indeed, Array.IndexOf has two advantages :
It allows searching if an element is included into an array,
It gets at the same time the index into the array.
int stringIndex = Array.IndexOf(arr, theString);
if (stringIndex >= 0)
{
// theString has been found
}
Inline version :
if (Array.IndexOf(arr, theString) >= 0)
{
// theString has been found
}
Using Contains()
string [] SomeArray = {"One","Two","Three"};
bool IsExist = SomeArray.Contains("One");
Console.WriteLine("Is string exist: "+ IsExist);
Using Find()
string [] SomeArray = {"One","Two","Three"};
var result = Array.Find(SomeArray, element => element == "One");
Console.WriteLine("Required string is: "+ result);
Another simple & traditional way, very useful for beginners to build logic.
string [] SomeArray = {"One","Two","Three"};
foreach (string value in SomeArray) {
if (value == "One") {
Console.WriteLine("Required string is: "+ value);
}
}