I'm trying to find, in an array of strings, which one starts with a particular substring. One of the strings in the array is guaranteed to start with the particular substring.
I tried to use:
int index = Array.BinarySearch (lines, "^"+subString);
Where lines is the array of strings and I'm looking for the index of the array that starts with subString. However, I'm either using regex improperly or there's a much better way to go about this?
BinarySearch can be used only to find a complete string, so you cannot use it for a substring match. You also have to ensure that the array is ordered in the first place to use BinarySearch.
You can use Array.FindIndex:
int index = Array.FindIndex(lines, line => line.TrimStart().StartsWith(subString));
Do you need to find the index of the (first) occurence, or do you need to find the actual strings that match that criterium?
myString.StartsWith(myPrefix); //returns bool
That should do the trick. Or a little more verbose:
var matchedLines = lines.Where(line => line.StartsWith(substring)).ToList();
If you need the index of the first occurence, I'd address it as an array:
var firstOccurence = String.Empty;
var firstOccurenceIndex = -1;
for(int i = 0; i < lines.Length; i++)
{
if(lines[i].StartsWith(substring))
{
firstOccurence = lines[i];
firstOccurenceIndex = i;
break;
}
}
Note: you don't HAVE to use an array. It could just as well have been done with a foreach, manual counter incrementor and a break statement. I just prefer to work with arrays if I'm looking for an index.
Yet, another solution:
int index = lines.ToList().FindIndex(line => line.TrimStart().StartsWith(subString));
Related
so my problem is that I don't know how to go forward in the list and print the next same integer if there is one.
Here is what I have at the moment:
while (list.Contains(input1))
{
Console.WriteLine(input1 + " is at index " + list.IndexOf(input1))
}
I am trying to list all of the integers that are in the list and print the index of them. But not remove after finding one of the integers (this was at least my first idea.).
IndexOf has an overload with two parameters, which allows you to start searching at a later position in the list.
Since this is obviously a learning exercise, I won't spoil it by providing the full code, but rather suggest that you try to implement the following algorithm:
Find the index of input starting at position 0.
If not found (i.e., IndexOf returns -1): we're done. Otherwise:
Print and remember that index.
Start again at step 1, but this time, don't start searching at 0 but at the index you remembered + 1.
You can do the following:
go through the list/array using for statement
for(int i=0; i < list.length; i++) // loop though list
then inside the loop check the value of the current item using if statement:
if(list[i] == input1)
//do smothing
The list[0] represent the first item in the array, which means the index is 0.
so in the example above the i will be the current index so long that you in the loop.
I didn't write the full code for learning purpose in reference to #Heinzi answer.
Hope that could be helpful!
This is an implementation possibility. It is longer than it has to be, but it makes it clearer for beginners how one could tackle this problem.
Since you wanted to only show numbers that come up more than once here is an implementation method. If you want to show numbers that come up only once too just erase everything about lastindex
List<int> yourlist = new List<int> { 1,1,1,1,1,11,2,3,3,4,4,5 };
int input = 0;
input = Convert.ToInt32(Console.ReadLine());
var index = yourlist.IndexOf(input);
//this checks if your input is in the list
var lastindex = yourlist.LastIndexOf(input);
//this does the same but it searches for the last implementation of your input
if (index != -1 && lastindex != index)
//this if checks if your number comes up more than once. IndexOf returns -1 if there is no occurence of your input
{
Console.Write($"the index of {input} is {index}");
for (int i = index+1; i <= yourlist.Count; i++)
//this loop takes the position of the first occurence of your number and then counts up from there
{
var tempindex = yourlist.IndexOf(input, i);
if (tempindex != -1)
//this if lets everything except -1 through
{
Console.Write($" and {tempindex}");
}
}
}
else
{
Console.WriteLine("your number cannot be found twice in the list");
}
I have six different arrays each with the same amount of elements in them, my question is, if I want to view the line that says 'test' and it happens to be the 22nd line, is there a way so that I can view the 22nd of all the arrays at the same time and then print them to the console, is it possible to do that?
e.g. I want to search through one array and then when it finds 'test' it prints out the same index of all arrays, including the one which 'test' was contained in.
Could a Binary Search be used here?
Thanks.
Yes you can.
Simply iterate through the first array until you find the string you are looking for, then use the counter to access the remaining arrays. Your code should look something like this:
for (int counter = 0; counter < Array1.Length; counter++)
{
if (Array1[counter] == "your string here")
{
//Print same line on remaining arrays, eg:
Console.WriteLine(Array2[counter]);
Console.WriteLine(Array3[counter]);
//Then you can break out of the loop
break;
}
}
If those are arrays, i can't see any problem doing this:
string[] array1, array2, array3..// etc
...
var stringToSearch = "someValue";
...
int matchPosition = Array.IndexOf(array1, stringToSearch);
if(matchPosition != -1)
{
// just sample of usage - access string by array2[matchPosition]
Console.WriteLine(array2[matchPosition]);
Console.WriteLine(array3[matchPosition]);
}
Is there a way to store every 2 characters in a string?
e.g.
1+2-3-2-3+
So it would be "1+", "2-", "3-", "2-", "3+" as separate strings or in an array.
The simplest way would be to walk your string with a loop, and take two-character substrings from the current position:
var res = new List<string>();
for (int i = 0 ; i < str.Length ; i += 2)
res.Add(str.Substring(i, 2));
An advanced solution would do the same thing with LINQ, and avoid an explicit loop:
var res = Enumerable
.Range(0, str.Length/2)
.Select(i => str.Substring(2*i, 2))
.ToList();
The second solution is somewhat more compact, but it is harder to understand, at least to someone not closely familiar with LINQ.
This is a good problem for a regular expressio. You could try:
\d[+-]
Just find how to compile that regular expression (HINT) and call a method that returns all occurrences.
Use a for loop, and extract the characters using the string.Substring() method, ensuring you do not go over the length of the string.
e.g.
string x = "1+2-3-2-3+";
const int LENGTH_OF_SPLIT = 2;
for(int i = 0; i < x.Length(); i += LENGTH_OF_SPLIT)
{
string temp = null; // temporary storage, that will contain the characters
// if index (i) + the length of the split is less than the
// length of the string, then we will go out of bounds (i.e.
// there is more characters to extract)
if((LENGTH_OF_SPLIT + i) < x.Length())
{
temp = x.Substring(i, LENGTH_OF_SPLIT);
}
// otherwise, we'll break out of the loop
// or just extract the rest of the string, or do something else
else
{
// you can possibly just make temp equal to the rest of the characters
// i.e.
// temp = x.Substring(i);
break; // break out of the loop, since we're over the length of the string
}
// use temp
// e.g.
// Print it out, or put it in a list
// Console.WriteLine(temp);
}
string dosage = "2/3/5 mg";
string[] dosageStringArray = dosage.Split('/');
int[] dosageIntArray = null;
for (int i = 0; i <= dosageStringArray.Length; i++)
{
if (i == dosageStringArray.Length)
{
string[] lastDigit = dosageStringArray[i].Split(' ');
dosageIntArray[i] = Common.Utility.ConvertToInt(lastDigit[0]);
}
else
{
dosageIntArray[i] = Common.Utility.ConvertToInt(dosageStringArray[i]);
}
}
I am getting the exception on this line: dosageIntArray[i] = Common.Utility.ConvertToInt(dosageStringArray[i]);
I am unable to resolve this issue. Not getting where the problem is. But this line int[] dosageIntArray = null; is looking suspicious.
Exception: Object reference not set to an instance of an object.
The biggest problem with your solution is not the missing array declaration, but rather how
you'd parse the following code:
string dosage = "2/13/5 mg";
Since your problem is surely domain specific, this may not arise, but some variation of two digits representing same integer.
The following solution splits the string on forward slash, then removes any non-digits from the substrings before converting them to integers.
Regex digitsOnly = new Regex(#"[^\d]");
var array = dosage.Split('/')
.Select(num => int.Parse(digitsOnly.Replace(num, string.Empty)))
.ToArray();
Or whatever that looks like with the cuddly Linq synthax.
You are looking for something like
int[] dosageIntArray = new int[dosageStringArray.Length];
You are trying to access a null array (dosageIntArray) here:
dosageIntArray[i] = Common.Utility.ConvertToInt(lastDigit[0]);
You need to initialize it before you can access it like that.
You have to allocate dosageIntArray like this:
in[] dosageIntArray = new int[dosageStringArray.Length];
Also, you have another bug in your code:
Index of last element of an array is Length - 1.
Your for statement should read as:
for (int i = 0; i < dosageStringArray.Length; i++)
or
for (int i = 0; i <= (dosageStringArray.Length - 1); i++)
The former is preferred and is the most common style you will see.
I strongly recommend you use Lists instead of Arrays. You don't need to define the size of the List; just add items to it. It's very functional and much easier to use.
As alternative approach:
var dosage = "2/3/5 mg";
int[] dosageIntArray = Regex.Matches(dosage, #"\d+")
.Select(m => int.Parse(m.Value))
.ToArray();
I am going to a directory picking up some files and then adding them to a Dictionary.
The first time in the loop the key needs to be A, second time B etc. Afer 26/Z the number represents different characters and from 33 it starts at lowercase a up to 49 which is lowercase q.
Without having a massive if statement to say if i == 1 then Key is 'A' etc etc how can I can keep this code tidy?
Sounds like you just need to keep an index of where you've got to, then some mapping function:
int index = 0;
foreach (...)
{
...
string key = MapIndexToKey(index);
dictionary[key] = value;
index++;
}
...
// Keys as per comments
private static readonly List<string> Keys =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopq"
.Select(x => x.ToString())
.ToList();
// This doesn't really need to be a separate method at the moment, but
// it means it's flexible for future expansion.
private static string MapIndexToKey(int index)
{
return Keys[index];
}
EDIT: I've updated the MapIndexToKey method to make it simpler. It's not clear why you want a string key if you only ever use a single character though...
Another edit: I believe you could actually just use:
string key = ((char) (index + 'A')).ToString();
instead of having the mapping function at all, given your requirements, as the characters are contiguous in Unicode order from 'A'...
Keep incrementing from 101 to 132, ignoring missing sequence, and convert them to character. http://www.asciitable.com/
Use reminder (divide by 132) to identify second loop
This gives you the opportunity to map letters to specific numbers, perhaps not alphabet ordered.
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
.Select((chr, index) => new {character = chr, index = index + 1 });
foreach(var letter in letters)
{
int index = letter.index;
char chr = letter.character;
// do something
}
How about:
for(int i=0; i<26; ++i)
{
dict[(char)('A'+ (i % 26))] = GetValueFor(i);
}