c# split string in 2. letter by letter - c#

I need split my string in 2, one letter to each variable.
Example: string = "ABCDEFGHIJ"
name1: ACEGI
name2: BDFHJ
I done so far:
var builderM = new StringBuilder();
var builderK = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
builderK.Append(s[i++]);
}
txtM.Text = builderM.ToString();
txtK.Text = builderK.ToString();
But its showing same text in the 2.

you should use ++i instead of i++
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if(i + 1 < s.Length) // to prevent IOR exception when count is odd.
builderK.Append(s[++i]); // pre increment.
}
the reason is that i++ is post incremented. that means i gets incremented after the expression therefor s[i++] will give you same item as s[i].

Another approach would be to use LINQ to filter odd and even indices into two strings, something like:
var even = new string(input.Where((c, idx) => idx % 2 == 0).ToArray());
var odd = new string(input.Where((c, idx) => idx % 2 != 0).ToArray());

If performance is not an issue, you can use LINQ:
var name1 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 0));
var name2 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 1));

You can also use the modulus operator (%) to determine if the index is even or odd, and put the even indexes in the first array and the odd indexes in the second one:
for (int i = 0; i < s.Length; i++)
{
if (i % 2 == 0) builderM.Append(s[i]);
else builderK.Append(s[i]);
}
If you'd rather increment the i inside the for body, you have to repeat the check against s.Length (as we do in the for condition). Also, you will need to either move the post-increment to the previous line (so that i is incremented in time), or use a pre-increment:
// Move post-increment to previous line example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i++]);
if (i < s.Length) builderK.Append(s[i]);
}
// Use a pre-increment example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if (++i < s.Length) builderK.Append(s[i]);
}

Related

Using Modulo instead of two loops

I'm new at programming in general and learning C# right now.
I just wrote a little programm where I have to step through an int[] in a specific pattern. The pattern is as follows:
Start at the last entry of the array (int i)
form the sum of i and (if avaible) the three entrys above (e.g. i += i-1 ... i += i-3)
Change i to i -= 4 (if avaible)
Repeat from step 2 until i = 0;
Therefore i wrote the following loop:
for (int i = intArray.Length - 1; i >= 0; i -= 4)
{
for (int a = 1; a <= 3; a++)
{
if (i - a >= 0)
{
intArray[i] += intArray[i - a];
intArray[i - a] = 0;
}
}
}
Now my new assignment is to change my code to only use 1 loop with the help of modulo-operations. I do understand what modulo does, but i can't figure out how to use it to get rid of the second loop.
Maybe somebody explain it to me? Thank you very much in advance.
While iterating over the array, the idea would be to use the modulo 4 operation to calculate the next index to which you will add the current value.
This should work with any array lengths:
for (int i = 0; i < intArray.Length; i++){
// we check how far away we are from next index which stores the sum
var offset = (intArray.Length - 1 - i) % 4;
if (offset == 0) continue;
intArray[i+offset] += intArray[i];
intArray[i] = 0;
}
iterating the array reversely makes it a bit more complicated, but what you wanted to get rid of inner loop with modulo is probably this:
var intArray = Enumerable.Range(1, 15).ToArray();
for (int i = 1; i < intArray.Length - 1; i ++)
{
intArray[i - (i % 4)] += intArray[i];
intArray[i] = 0;
}

How to convert For Loop results into an Array then count the integers of the resulting Array in C#?

In C#, how would I go about converting the result of a For Loop into an Array and count (Display on the Console) the number of integers stored in that converted array?
Please see below for what I have thus far:
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
Console.WriteLine(i);
}
}
And feel free to let me know if there is a different way to count the results of the code I have above.
Please let me know what you think.
There are a few different ways to accomplish what you're after. You can use a for-loop as you've done and accomplish it like so:
var list = new List<int>();
var sum = 0;
for (var i = 1; i < 100; i++)
{
if (i % 3 != 0)
continue;
list.Add(i);
Console.WriteLine(i);
sum += i;
}
Console.WriteLine($"Count: {list.Count}");
Console.WriteLine($"Sum: {sum}");
You could also accomplish this with Linq:
var numbers = Enumerable.Range(1, 99)
.Where(i => i % 3 == 0)
.ToList();
var sum = numbers.Sum();
numbers.ForEach(Console.WriteLine);
Console.WriteLine($"Count: {numbers.Count}");
Console.WriteLine($"Sum: {sum}");
You can use List for that purpose:
var list = new List<int>();
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
list.Add(i);
Console.WriteLine(i);
}
}
Console.WriteLine(list.Count);
There is no need to insert the numbers into a collection to count them. Just use a variable as counter
int count = 0;
for (int i = 1; i < 100; i++)
{
if (i % 3 == 0)
{
count++; // Increments count by 1.
Console.WriteLine(i);
}
}
Console.WriteLine("The count is " + count);
List<int> myList = new List<int>();
for (int i = 1; i < 100; i++) {
if (i % 3 == 0) {
Console.WriteLine(i);
myList.Add(i);
}
}
Console.WriteLine(myList.Count);
//if you want an array....
int[] myArray;
myArray = myList.ToArray();

Using variable value as for loop index

I have a code which contains 2 for loops:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count]; count++)
{
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
var dOpt = new DataGridObjectOpt();
double Closest_Goallvl = list_Level.Aggregate((x, y) => Math.Abs(x - Initial_Lvl) < Math.Abs(y - Initial_Lvl) ? x : y);
dOpt.ImageSource = new Uri(filePaths[a], UriKind.RelativeOrAbsolute);
dOpt.Level_Index = Initial_Lvl;
dOpt.Level_Goal = goallvl;
dOpt.Stage = 1;
LOpt_Temp.Add(dOpt);
}
count = a;
int best_Profit_Ind = LOpt_Temp.FindIndex(x => x.TotalCost == LOpt_Temp.Max(y => y.TotalCost));
LOpt.Add(LOpt_Temp[best_Profit_Ind]);
dataGridOpt.ItemsSource = LOpt;
}
I want the loops to begin at 0, however once the inner loop ends for the first time and ends at a value of a, i want the outer loop to begin from this place now.
For example, first loop begins at 0, inner loop exits when a=6. Now i want count to start for 6 and not 1.
Thank you.
As #dcg mentioned, do count+=a-1 before iterating again. As #dlatikay mentioned, you could run into IndexOutOfRangeException. To avoid that, add and condition in the outer for loop. So that your final code looks something like this:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count] && count < list_Level.Count; count++)
{
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
//Your code
}
count+=a-1
//Your code
}
Notice the middle condition in the outer for loop. Hope it helps.
First of all
list_Level[count] < list_Level[list_Level.Count]
by using this condition you will get IndexOutOfRangeException you should use
list_Level[count] < list_Level[list_Level.Count - 1]
something like that.
on the other hand this may help you:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count - 1] && count < list_Level.Count; count++){
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
//Your code
}
count = a-1;
if(count >= list_Level.Count)
{
break;
}
//Your code
}

How can i check if the specific strings exist in a List<string> and if not to remove the indexs from the List?

I tried this but this is not working.
I'm getting index out of bound exception.
for (int x = 0; x < newText.Count; x++)
{
for (int y = 0; y < WordsList.words.Length; y++)
{
if (!newText[x].Contains(WordsList.words[y]))
{
for (int n = 0; n < 3; n++)
newText.RemoveAt(x);
}
}
}
newText is a List
words is string[]
newText format is like this:
index 0 = this is a text hello all
index 1 = time&date (6/14/2014....)
index 2 = empty ""
index 3 = text hello world
index 4 = time&date (6/14/2014....)
index 5 = empty ""
And so on...
What i want to do is to loop over newText and if in index 0 there no any word(string) from words then remove index 0,1,2 next itertion check index 3 for any words if not exist one word or more remove indexs 3,4,5.
If in index 0 or 3 there is one word or more then do nothing dont remove anything.
In the end newText should be in the same format as before:
index 0 text line
index 1 date&time
index 2 empty ""
Just the new newText content will be with text lines that contain one ore more strings from words.
EDIT
This is what i tried now:
First this is how i build the List:
List<string> t = filterNumbers(text);
for (int i = 0; i < t.Count; i++)
{
if (!newText.Contains(t[i]))
{
newText.Add(t[i]);
newText.Add(dateTime[i]);
newText.Add("");
}
}
Removing numbers and leave only text and add it.
In the end in this case i have in newText 150 indexs. That's 50 indexs of text lines.
Then i tried this:
int lastindex = newText.Count - 1;
for (int i = newText.Count - 1; i >= 0; i--)
{
for (int x = 0; x < WordsList.words.Length; x++)
{
if (!newText[i].Contains(WordsList.words[x]))
{
if (i != lastindex)
{
newText.RemoveAt(i + 1);
}
newText.RemoveAt(i);
}
}
}
But i'm getting exception on the line:
if (!newText[i].Contains(WordsList.words[x]))
Index was out of range. Must be non-negative and less than the size of the collection
EDIT
If I understood correctly that you wanted to check whether a specific line contains some words and if not remove that and the two following lines, here is a possible solution:
// start at the bottom in the first line "that matters" and go down by 3
for (int x = newText.Count - 3; x >= 0; x-=3)
{
// check if the line contains any of the words specified
if (!WordsList.words.Any(w => newText[x].Contains(w)) || newText[x] == "")
{
// remove the checked line as well as the next two if not
l.RemoveRange(x, 3);
}
}
EDIT
Corrected the predicate to:
!WordsList.words.Any(w => newText[x].Contains(w));
from
!WordsList.words.Any(w => newText.Contains(w));
EDIT 2
Added the empty string as possibility
The problem was that if the line to test was empty, it would pass the test because it does not contain any word from WordsList.words. The test now includes the empty string as an option and removes it when encountered.
Looking at your logic:
(1) for (int i = newText.Count - 1; i >= 0; i--)
{
(2) for (int x = 0; x < WordsList.words.Length; x++)
{
if (...)
{
(3) newText.RemoveAt(i);
}
}
}
You can see that even if you removed lines in (3), you continue loop in (2) which can try again remove line in (2) for new indexes, which now become out of bounds
you need to add break after (3) to continue loop (1)
// For each 3-word-sets
for (int x = 0; x < newText.Count; x += 3)
{
// For each word in that 3-word-set
for (int k = x; k < 3; k++)
{
// Check each word
bool breakOut = false;
for (int y = 0; y < WordsList.words.Length; y++)
{
if (!newText[k].Contains(WordsList.words[y]))
{
newText.RemoveAt(x+2);
newText.RemoveAt(x+1);
newText.RemoveAt(x);
x -= 3;
breakOut = true;
break;
}
}
if (breakOut) { break; }
}
}
I just wanted to test and experiment with your original code. Haven't tested this. Just make sure the list contains 3×n items.
Ok, it seems your data structure is really bad. Anyway if you have to keep the structure as is I think this can work :
var newList = new List<string>();
for (int index = 0; index < newText.Count; index = index + 3)
{
if (WordsList.Any(t => newText[index].ToLower().Trim().Contains(t.ToLower().Trim())))
{
newList.AddRange(newText.Skip(index).Take(3));
}
}
newText = newList;

How to count word occurrences in an array of strings using c#?

I'm new to programming, and I am trying to write a program that take in an array of strings (each index of the array being a word) and then count the occurrences of each word in the string. This is what I have so far:
string[] words =
{
"which",
"wristwatches",
"are",
"swiss",
"wristwatches"
};
Array.Sort (words);
for (int i = 0; i < words.Length; i++)
{
int count = 1;
for(int j = 1; j < words.Length; j++)
{
if (words [i] == words [j])
{
count++;
}
}
Console.WriteLine ("{0} {1}", words[i], count);
}
Ideally, I would like the output to be something like:
are 1
swiss 1
which 1
wristwatches 2
The problems with your code are (1) double-counting and (2) skipping the initial element in the nested loop.
You double-count because you ignore situations when i == j; you skip the initial element because you set int j = 1.
The shortest solution is to use LINQ, like this:
var counts = words
.GroupBy(w => w)
.Select(g => new {Word = g.Key, Count = g.Count()})
.ToList();
Now you can print the results like this:
foreach (var p in counts) {
Console.WriteLine("Word '{0}' found {1} times", p.Word, p.Count);
}
There are certainly more efficient ways of handling this (take a look at dasblinkenlight's answer for an extremely good one) but asssuming you'd like to keep relatively the same code, you should change your second for loop to something along these lines:
for(int j = i+1; j < words.Length; j++)
{
if (words [i] == words [j])
{
count++;
}
else break;
}
Here are the two changes I made:
1) You should initialize j to i+1; You want to check if any of the rest of the Strings are equal to words[i], and the rest of the strings will start at i+1, not 1 (unless i=0).
2) For the sake of efficiency, you'll want to break out of the second loop if the two string aren't equal; since you sorted the array alphabetically, if the word you're currently looking at isn't equal, none of the ones after it will be either.
var occrs = words.GroupBy(x => x.ToLower())
.ToDictionary(g => g.Key, g => g.Count());
foreach(var pair in occrs)
Console.WriteLine(pair.Key + " " +pair.Value);
For your understanding purpose use String.Compare()
int Duplicate = words.Lenth + 1; //any value not in the range of the string array
for (int i = 0; i < words.Length; i++)
{
int count = 1;
for(int j = 0; j < words.Length; j++)
{
if(i != j) //to avoid same string comparison
{
if (string.Compare(words [i],words [j]) == 0) //or else .Equals(0)
{
count++;
Duplicate = j;
}
}
}
if(i != Duplicate)
{
Console.WriteLine ("{0} {1}", words[i], count);
}
}
This will not print again the same value.
Make use of dictionary data structure. Here the dictionary will store key as word and value as word count. Insert all the words in dictionary. If the word inserted word is new, set the value of the word key to 1 , otherwise increment the word-key value by 1.
Dictionary<string, int> wordCount = new Dictionary<string, int>();
// Insert a word in the dictionary if it exits, otherwise increment
//the count of the word
for (int i = 0; i < words.Length; i++)
{
try
{
wordCount.Add(words[i], 1);
}
catch (Exception)
{
wordCount[words[i]] += 1;
}
}
// display word and it's corresponding word count
foreach (var item in wordCount)
{
Console.WriteLine ("{0} {1}", item.Key, item.Value);
}

Categories