I have a method, I want to be able to verify a string array inside the method. But how would I do it if the string array increase and decrease by the amount of values for example one string might have 2 items, and the next might have 3 items in the string array??
If I have a string that is more than what i have inside the method, i get error: System.IndexOutOfRangeException: Index was outside the bounds of the array.
Here's my method so far:
string1 = "item1, item2";
string2 = "item01, item02, item03";
private void VerifyArrayString(string theString)
{
var elements = theString.Splitnew[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
for(int i=0; i<elements.Length; i +=1)
{
if(elements[0] != null)
{
//do something
}
if(elements[1] != null)
{
//do something
}
// and so and so with the next items....
}
}
If you're asking how to make sure you have enough elements for what you're trying to do, you would have to do something like this:
string string1 = "item1, item2";
string string2 = "item01, item02, item03";
private void VerifyArrayString(string theString)
{
var elements = theString.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
if (elements.Length >= (minimumNumber))
{
for (int i = 0; i < elements.Length; i += 3)
{
if (elements[0] != null)
{
//do something
}
if (elements[1] != null)
{
//do something
}
// and so and so with the next items....
}
}
}
Or if you want to be able to change some numbers and not all, you'd have to go through each one you're changing and make sure you have the right length, such as:
if(elements.Length > 0 && elements[0] != null)
{
//do something
}
//etc etc etc
Revised for clarity:
Based on your comment, you'll want to check your array length each time you're trying to manipulate one of the values of the array. Here is the example code:
string string1 = "item1, item2";
string string2 = "item01, item02, item03";
private void VerifyArrayString(string theString)
{
var elements = theString.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
for(int i=0; i<elements.Length; i++)
{
if(elements[i] != null)
{
//do something
}
}
}
You can use LINQ to filter with Enumerable.Where:
private void VerifyArrayString(string theString)
{
var elements = theString.Split(new[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
foreach (var element in elements.Where(el => !string.IsNullOrEmpty(el))
{
if (element == "SomeString")
{
// Do Something
}
}
}
This will only yield elements which are not null or an empty string.
Related
I have an error on this part foreach( string code in text ) the error is saying can not convert char to string. how do i convert this to string
my list
class MyCipher : ICipherDecipher
{
private List<Code> alphabet;
public MyCipher()
{
alphabet = new List<Code>();
alphabet.Add(new Code("Aca", " 1234"));
alphabet.Add(new Code("Bb", " 1234"));
alphabet.Add(new Code("C1", " 1234"));
}
this is where im gtting the error on the foreach part , its saying cant convert to string from char
private string Cipher( string text )
{
StringBuilder result = new StringBuilder();
foreach( string code in text )
{
Code element =
alphabet.Where(x => x.MyCode == code.ToString()).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
Edited code
class MyCipher : ICipherDecipher
{
private List<Code> alphabet;
public MyCipher()
{
alphabet = new List<Code>();
alphabet.Add(new Code("4", " take 4"));
alphabet.Add(new Code(" ", " a"));
alphabet.Add(new Code("4d", " for 4 days"));
}
public string Cipher(params string[] codes)
{
StringBuilder result = new StringBuilder();
foreach (string code in codes)
{
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if (element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
class Code
{
public string MyCode;
public string MyDecoded;
public Code(string code, string decode)
{
MyCode = code;
MyDecoded = decode;
}
}
}
Button code
public partial class Form1 : Form
{
private ICipherDecipher myCipher;
public Form1()
{
myCipher = new MyCipher();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string textToBeCiphered = textBox1.Text;
string textCiphered = myCipher.Cipher(textToBeCiphered);
textBox2.Text = textCiphered;
}
}
Change this part of your code:
foreach( char code in text )
{
Code element =
alphabet.Where(x => x.MyCode == code.ToString()).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
Then everywhere you use code you convert it to string by using code.ToString()
You're iterating over a string (text), so the code variable should be a char, not a string:
foreach( char code in text )
Alternatively, you can use var:
foreach( var code in text )
to make the compiler automatically assign the type it thinks it should be, but you should still be aware of the type it actually is because it impacts the operations the variable supports.
Going a bit deeper into it, some other languages (especially dynamic languages like JavaScript and Python) don't make this distinction but C# (like most other C-like languages) has a char datatype that holds a single element of the text. In the case of C#, that type holds a UTF-16 code unit. (Which is not always the same as a user-visible character, but that's a whole other story).
Based on the discussion in the comments, it seems you want to match the whole string instead of characters of the string. In that case you have two options, depending on what you want to do:
If you want the Cypher method to receive a single string and get the code that matches that string, just get rid of the loop and match against the parameter directly:
private string Cipher( string code )
{
StringBuilder result = new StringBuilder();
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
return result.ToString();
}
Alternatively, if you want to pass multiple strings and process all of them, pass an IEnumerable<string> (from System.Collections.Generic) or a derived type such as string[]:
private string Cipher( IEnumerable<string> codes )
{
StringBuilder result = new StringBuilder();
foreach( string code in codes )
{
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
// Usage examples:
private string CallSite() {
// (These are just some of the options, other enumerable types
// will work as well as long as they enumerate over strings)
return Cypher( new[] { "Aca", "Bb" });
return Cypher( new List<string> { "Aca", "Bb" });
}
Alternatively, if you replace IEnumerable<string> with params string[] you can call the function as if it had any number of string parameters:
private string Cipher( params string[] codes )
{
// ... (as above)
}
// Usage example:
private string CallSite() {
return Cypher( "Aca", "Bb" );
}
In any of these cases, you can get replace code.ToString() with simply code because it already is a string (and "string".ToString() just returns itself).
I am making a web service for an app with Tesseract Ocr 3.02.
I want to create variables on depending of how many informations I get on the business card and after that classify information from a string.
For example:
Tel. +496123456789$Mobil +49123456789$kai.kalsbach#gmail.com$www.google.com$Kai Kalsbach$Muster Str 1a$40599 Düsseldorf$"
And then like this:
-Telephone number
-First Name
-Last Name
-Email
-Address
That was my first idea:
string endText1 = text.Split('$')[0];
string endText2 = text.Split('$')[1];
string endText3 = text.Split('$')[2];
string endText4 = text.Split('$')[3];
string endText5 = text.Split('$')[4];
string endText6 = text.Split('$')[5];
string endText7 = text.Split('$')[6];
string endText8 = text.Split('$')[7];
and after that i would classify the variables.
but in many cases I get the following exception because the number of informations can vary depending of business card.
System.IndexOutOfRangeException: Index was outside the bounds of the array c#
The IndexOutOfRangeException exception is thrown because the code tries to access an item outside the array length.
My proposition : I created formattedArray with contains always 8 items and I copied the splited array to this formattedArray. With that, you have no more IndexOutOfRangeException because the item missing in text.Split('$') is null in formattedArray
var a = text.Split('$');
var formattedArray = new string[8];
Array.Copy(a, formattedArray, a.Length);
string endText1 = formattedArray [0];
string endText2 = formattedArray [1];
string endText3 = formattedArray [2];
string endText4 = formattedArray [3];
string endText5 = formattedArray [4];
string endText6 = formattedArray [5];
string endText7 = formattedArray [6];
string endText8 = formattedArray [7];
string[] Splitted = text.Split('$');
And you mentioned you want to make a decision based on the number of elements the split spits out
int Count = Splitted.Length;
switch(Count)
{ case 0: //DoStuff
break;
....
default:
break;
}
In your case, it is better to use the following:
string[] stringList = text.Split('$');
foreach(string val in stringList)
{
//your logic.
}
You can split the string once using the .Split method.
Then afterwards run it in a foreach or for loop. I believe your logic is based on the amount of strings, so you are looking for a 'for' loop.
string[] split = text.Split('$');
for (int i = 0; i < split.Length; i++)
{
var text = split[i];
// Your logic here...
switch (i) // for logic based on the index of the string
{
case 0:
// do something
break;
case 1:
// do something
break;
}
}
The IndexOutOfRangeException exception is thrown because the code tries to access the 8th item in a 7-item array :
string endText8 = text.Split('$')[7];
Indexes in .NET collections are 0-based which means 7 refers to the 8th element.
By default, String.Split will return empty fields as well. This means that either the string isn't the same as the one posted here, or that the StringSplitOptions.RemoveEmptyEntries was used
String.Split returns a string array that can be stored in a string[] variable. There's no need to repeat String.Split, or use multiple variables :
var items = text.Split(new[]{'$'},StringSplitOptions.RemoveEmptyEntries);
Creating a class from this array is simple enough that you probably don't need to create a custom parser :
class Record
{
public string Telephone {get;set;}
...
}
var items = text.Split('$');
var record=new Record
{
Telephone=items[0],
Mobile=items[1],
...
};
Another easy way to do that is to use a try, then all variables will be created until the index has reached its maximum.
string[] strArray = text.Split('$');
Try {
string endText1 = strArray[0];
string endText2 = strArray[1];
string endText3 = strArray[2];
string endText4 = strArray[3];
string endText5 = strArray[4];
string endText6 = strArray[5];
string endText7 = strArray[6];
string endText8 = strArray[7];
}
catch
{
//nothing
}
Create factory and recognizers
public class PhoneItem : IItem
{
public PhoneItem(string text)
{
// some code
}
}
public interface IRecognizer
{
IItem Recognize(int index, string text);
}
public class PhoneRecognizer : IRecognizer
{
public IItem Recognize(int index, string text)
{
return index == 0 ? new PhoneItem(text) : null;
}
}
public class ItemFactory
{
private IEnumerable<IRecognizer> _recognizers = new []
{
new PhoneRecognizer(),
new FullNameRecognizer()
};
public IItem CreateItem(int index, string text)
{
foreach (var rec in _recognizers)
{
var item = rec.Recognize(index, text);
if (item != null)
{
return item;
}
}
throw new Exception("Item not recognized");
}
}
Split string to pieces
var parts = text.Split('$');
Use the factory to create objects
var factory = new ItemFactory();
var items = new List<IItem>();
for (int i = 0; i < parts.Length; i++)
{
items.Add(factory.CreateItem(i, parts[i]));
}
// do whatever you wants
I have a string array and it always gives string array length > 0. what is the correct way to check that the string array is not null.
string[] mystr = new string[0];
...
...
if (..) {
mystr = string[] oldstrArray.Clone();
}
...
...
if (mystr[0].Length != 0) {
//Always enters this loop even if mystr is not assigned in the above if condition
}
Try this code snippet:
private static void Main(string[] args)
{
string[] mystr = null;
if (IsNullOrEmpty(mystr))
{
//Do your thing
}
}
static bool IsNullOrEmpty(string[] strarray)
{
return strarray== null || strarray.Length == 0;
}
Or this one (Extension Method)
class MyAwesomeProgram
{
private static void Main(string[] args)
{
string[] mystr = null;
if (mystr.IsNullOrEmpty())
{
//Do what you want
}
}
}
static class Extensions
{
public static bool IsNullOrEmpty(this string[] strarray)
{
return strarray == null || strarray.Length == 0;
}
}
You're asking for the length of the first string in the array, not the array itself. You want to check for mystr.Length instead of mystr[0].Length.
Also, pay attention to the code you're posting - it should compile (LINQPad is very useful for this). Yours has syntax errors, which may hinder people trying to help you.
string[] mystr = new string[] { "", null, "", "", null };
//Check if the array itself is null which is what your question is truly asking
if (mystr == null)
Console.WriteLine("Array is null");
//Check to see if the array itself is empty/zero-length
if (mystr != null && mystr.Length == 0)
Console.WriteLine("Array contains no elements");
//Check if all elements are null or empty
if (mystr != null && mystr.All(s => string.IsNullOrEmpty(s)))
Console.WriteLine("All elements are either null or empty");
if (mystr[0].Length != 0)
It will give you the length of first member of the array. Null check is simple
if(mystr == null)
Length property gives you the size of the array. Length can be used to check empty array
This question already has answers here:
Change strings from one string to another in an array based on a condition
(8 answers)
Closed 9 years ago.
I have an array of strings, most of which are values "true" or "false" some are not and are to remain as are.
I wish to loop through the array and change any "true" or "false" to 1' or zero's
I have kind of started it, but am struggling with the syntax
string[] data = args.Trim().Split(',');
// Loop over strings
foreach (string s in data)
{
if(s == "true")
{
Convert.ToInt32(s)=1;????
}
else if(s == "false")
{
??????
}
}
please can someone offer some guidance
Perhaps with Linq:
string[] data = args.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => StringComparer.OrdinalIgnoreCase.Equals("true", s.Trim()) ? "1"
: StringComparer.OrdinalIgnoreCase.Equals("false", s.Trim()) ? "0" : s)
.ToArray();
Added the StringComparer.OrdinalIgnoreCase to show how you can ignore the case if desired.
Here's a demo with the sample string commented.
this,1,is,not,0
Write a function like this. You can then copy the "converted data" into a new List and return it as an array, or whatever.
public string[] GetData()
{
string[] data = args.Trim().Split(',');
List<string> returnData = new List<string>();
// Loop over strings
foreach (string s in data)
{
if(s == "true"){
returnData.Add("1");
}
else if(s == "false"){
returnData.Add("0");
}
else
returnData.Add(s);
}
return returnData.ToArray();
}
made a presumption you want an array of type string as you don't specify.
Other options as it's unclear what your going to do with the two types of data are to parse the values when you get them out, or split them up into two lists.
string[] rawDatas = GetData();
foreach(string rawData in rawDatas)
{
short iRawData;
if (Int16.TryParse(rawData, out iRawData))
{
if (iRawData == 1 || iRawData == 0)
{
//Add a bit
iRawData;
}
else
{
// add a string
rawData;
}
}
else
{
//add a string
rawData;
}
}
OR
public void GetData(out List<string> strings, out List<Int16> shorts)
{
string[] data = args.Trim().Split(',');
strings= new List<string>();
shorts = new List<Int16>();
// Loop over strings
foreach (string s in data)
{
if(s == "true"){
shorts.Add(1);
}
else if(s == "false"){
shorts.Add(0);
}
else
returnData.Add(s);
}
}
OR
add to an array of object, though this will need casting back on the other side, which is inefficent (see boxing and unboxing)
public object[] GetData()
{
string[] data = args.Trim().Split(',');
List<object> returnData = new List<object>();
// Loop over strings
foreach (string s in data)
{
if(s == "true"){
returnData.Add(1);
}
else if(s == "false"){
returnData.Add(0);
}
else
returnData.Add(s);
}
return returnData.ToArray();
}
if you just want to do 0 and 1 than
string[] data = args.Trim().Split(',');
int[] a = new int[data.length];
// Loop over strings
int count=0;
foreach (string s in data)
{
if(s == "true"){
int a[count] = 1;
}
else if(s == "false"){
int a[count]=0;
}
else
{
a[count] = Convert.ToInt32(s);
}
count++;
}
or with linq
var intlst = data.
Select(input => input == "true" ? 1 :
(input == "false" ? 0 : Convert.ToInt32(input)));
Try this:
var result = data.Select(input => input == "true" ? 1 : (input == "false")? 0 : -1);
You can do this by simple for loop:
List<string> newArgs = new List<string>();
for (int i = 0; i <= args.Length - 1; i++)
{
newArgs.Add(args[i] == "true" ? "1"
: args[i] == "false" ? "0"
: args[i]);
}
Or by using linq which will internally use extension object to iterate through the collection.
Well the problem that I can see you running into is holding the variables themselves without creating a new array. When you type the line
string[] data = args.Trim().Split(',');
you are declaring that the variables within that array are of type string. If you wish to convert them to integers you will need to create a new array of integers or undefined type. I think you are using C# which I believe the code for multiple types in an array is
object[]
In that case you would do something like
object[] data = args.Trim().Split(',');
foreach(string s in data){
if(s == "true"){
s = 1;
Convert.ToInt32(s);
}
else if(s == "false"){
s = 0;
Convert.ToInt32(s);
}
}
I am trying to split my list of strings at each separate lines using the String.Split method but the both the method below and a regex method did not work. Instead, they returned the following result {0}
0. System.String[] instead of the actual array of strings. Please help to find the error(s) in the code below:
string m_settings_temp;
string[] m_settings;
public void ShowSettingsGui() {
var dialog = new OpenFileDialog { Filter = "Data Sources (*.ini)|*.ini*|All Files|*.*" };
if (dialog.ShowDialog() != DialogResult.OK) return;
m_settings_temp = File.ReadAllText(dialog.FileName);
m_settings = m_settings_temp.Split(new [] { '\r', '\n' });
//This regex method failed as well:
//m_settings = Regex.Split(m_settings_temp,"\r\n|\r|\n");
}
//The method below is to evaluate the output
protected override void SolveInstance(IGH_DataAccess DA)
{
if (m_settings == null)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "You must declare some valid settings");
return;
}
DA.SetData(0, m_settings);
}
Thanks in advance!
just use ReadAllLines like this
m_settings = File.ReadAllLines(dialog.FileName);
this will give you a string[] with an element for each line in the selected file. If, after running this code, m_settings has no elements, the file you selected was empty.
If I wanted to interrgoate the contents of m_settings in a console app I might do somthing like.
for (var i = 0; i < m_settings.Length; i ++)
{
Console.WriteLine(m_settings[i]);
}
This would output the content of array, one element at a time. If I used the implementation of ToString for am array, like this,
Console.WriterLine(m_settings);
I would get a string representation of the array's type and the number of elements it contains.
I suspect in your case you want to do somthing like
protected override void SolveInstance(IGH_DataAccess DA)
{
if (m_settings == null || m_settings.Length == 0)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
"You must declare some valid settings");
return;
}
for (var i = 0; i < m_settings.Length; i ++)
{
DA.SetData(i, m_settings[i]);
}
}
m_settings = m_settings_temp
.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
string m_settings_temp;
string[] m_settings;
public void ShowSettingsGui()
{
var dialog = new OpenFileDialog { Filter = "Data Sources (*.ini)|*.ini*|All Files|*.*" };
if (dialog.ShowDialog() != DialogResult.OK) return;
m_settings_temp = File.ReadAllText(dialog.FileName);
m_settings = m_settings_temp.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
}