In my code I have string array of 1000 indexes and it contain unique string data. Now, I want to make duplicate of some of them string element without overwriting next element. To summarize I would like to shift the array and inserting a duplicate value.
Here my code is,
for (int r = 0; r < sResultarray1.Length; r++)
{
if (sResultarray1[r] != null &&
sResultarray1[r].Contains("WP") &&
sResultarray1[r].Contains("CB") == true)
{
index = Array.IndexOf(sResultarray1, sResultarray1[r]);
for (int e = 1000; e >= index + c; e--)
{
sResultarray1[e] = sResultarray1[e - c];
}
break;
}
}
My current output is
++ST110+WP001.CB001
++ST120+WP001.CB001
++ST120+WP002.CB001
++ST130+WP001.CB001
++ST110+WP001.CB001
++ST120+WP001.CB001
++ST120+WP002.CB001
++ST130+WP001.CB001
My desired output is
++ST110+WP001.CB001
++ST110+WP001.CB001
++ST120+WP001.CB001
++ST120+WP001.CB001
++ST120+WP002.CB001
++ST120+WP002.CB001
++ST130+WP001.CB001
++ST130+WP001.CB001
Does anyone help me out to solve this problem?
I suggest using different collection type - List<string> instead of String[] (at least temporarily): Add, Insert ("shift and add") are not operations array has been designed for. Something like this:
using System.Linq;
...
// Temporal collection - list
List<string> list = sResultarray1.ToList();
// Downward - we don't want to check the inserted item
for (int r = list.Count - 1; r >= 0; --r) {
if (list[r] != null && list[r].Contains("WP") && list[r].Contains("CB")) {
// if you want to insert - "shift and add duplicate value" - just insert
list.Insert(r + 1, list[r]);
}
}
// back to the array
sResultarray1 = list.ToArray();
Related
I have a use case where, given a huge list of strings and one specific string value pulled from a DataGridView row containing those same elements in the same order, I need to find if the list contains another identical entry. All the existing posts I checked just tell you if there are duplicates period. Here is what I have so far :
List<int> indexes = new List<int>{-1, originalRow.Index};
int foundIndex = CompleteScancodeList.IndexOf(originalRow.Cells[1].Value.ToString());
if (!indexes.Contains(foundIndex))
{
//Do something
}
The originalRow variable is a DataGridViewRow that is pulled from iterating over every row of a DataGridView. What I'm effectively doing here is saying : if the index of that element in the list is not -1 and not the same index as the row's index (therefore literally the same element).
I initially managed to make it work with a nested loop but it was too slow for my liking. How can I make this work the way I want where this condition will only evaluate to true if a given string value is present in a string list but at a different index than the original?
This works, kinda... It only works if the duplicated element is before the original element in the list. Similarly, if I use the LastIndexOf method, it only works if the duplicated element is after.
I'm from phone, sorry for terrible formatting and typos. So, tell if list have duplicates:
if (list.Count != list.Distinct().Count) { // list has dupes }
Find particular duplicates and handle them:
var set = new HasSet<int>();
foreach (var item in list) {
if (!set.Add(item)) {
// handle it
}
}
You can replace foreach with for loop if you need actual indexes in array.
this is an example how to find the duplicate numbers in a list and store the unique values selected from first list into the second list
List<int> LST = new List<int> { 10, 34, 43, 75, 10, 67, 30, 200, 30, 100, 30 };
List<int> LST_2 = new List<int>();
for (int i = 0; i < LST.Count; i++)
{
for (int j = i + 1; j < LST.Count; j++)
{
if (LST[j] == LST[i])
{
if (!LST_2.Contains(LST[i]))
{
LST_2.Add(LST[i]);
}
}
}
}
foreach (var N in LST_2)
{
Console.WriteLine(N);
}
i wish this help you
Once you have the first index of the value you're searching for:
string searchedValue = originalRow.Cells[1].Value.ToString();
int foundIndex = CompleteScancodeList.IndexOf(searchedValue);
You can use linq .Skip() method to get only the remaining elements. Then use .Any(), which will stop executing once the condition is met.
CompleteScancodeList.Skip(foundIndex).Any(entry => entry == searchedValue);
But it's still iterating twice, once for IndexOf and once for Any.
//Search the index of first element
int foundIndex = CompleteScancodeList.IndexOf(originalRow.Cells[1].Value.ToString());
//If the index found is row's index
if(foundIndex == originalRow.Index)
//Search the index of next element
foundIndex = CompleteScancodeList.IndexOf(originalRow.Cells[1].Value.ToString(), originalRow.Index + 1);
//If something is found
if (foundIndex != -1)
{
//Do something
}
Other solution with explicit loop :
var hasDuplicate = false;
var index = 0;
foreach(var element in CompleteScancodeList)
{
if(element == originalRow.Cells[1].Value.ToString() && index != originalRow.Index)
{
hasDuplicate = true;
break;
}
index++;
}
if (hasDuplicate)
{
//Do something
}
I am fairly new to C#, so I'm sorry if this is a simple question
--
I have a list of stock objects and I am using a for loop to go backwards through the list. Each property of the stock object is set to a textbox to display the value and there is a button that allows the user to cycle through each object, changing the values of the textboxes.
I need to tell if I reach the beginning of the list so that I can deactivate the button that allows the user to go backwards through the list.
Note -
The Count is > 1 because I had to skip the first item in the list.
Here is my code:
if (stockList.Count > 1)
{
for (int i = stockList.Count - 1; i >= 0; i--)
{
txtName.Text = stockList[i].Name;
numLastPrice.Value = stockList[i].LastPrice;
numOpeningPrice.Value = stockList[i].OpeningPrice;
numLowPrice.Value = stockList[i].LowPrice;
numHighPrice.Value = stockList[i].HighPrice;
if (i == ???)
{
txtName.Text = stockList[i].Name;
numLastPrice.Value = stockList[i].LastPrice;
numOpeningPrice.Value = stockList[i].OpeningPrice;
numLowPrice.Value = stockList[i].LowPrice;
numHighPrice.Value = stockList[i].HighPrice;
btnBack.Enabled = false;
}
}
If you have 10 items in that list, then you're going backwards from 9 to 0 (indexes are zero based by default)
In your case, 0 indicates the first item in your list, so just check the index is 0
if (i == 0)
(edit after reading comments)
in your for loop you declare i as an int with the value of .Count - 1:
for (int i = stockList.Count - 1; i >= 0; i--)
so in your loop i is just a variable, but as a result of the way you declared it, it will also be the index value of your list as you iterate through the loop.
Hope that helps.
I hope that the following snippet helps you see the relationship between i and the list:
var myList = new List<string>() { "A", "B", "C", "D", "E" };
for (int i = myList.Count() - 1; i >= 0; i--)
{
Console.WriteLine($"i:{i}, myList[{i}]={myList[i]}");
if (i == 3)
{
//I can access the elements at an index different than `i`
Console.WriteLine($"i:{i}, Seaky peek at the 5th element (index 4): {myList[4]}");
}
}
// This would cause a compilation error because `i` is being used outside of `for`
//i = 100; // Error: The name 'i' does not exist in the current context
Console.WriteLine($"First item is myList[0] and is '{myList[0]}'");
Console.WriteLine($"Last item is myList[myLIst.Count()-1] ans is '{myList[myList.Count() - 1]}'");
// Let's go through the list again
for (int someNameForIndex = myList.Count() - 1; someNameForIndex >= 0; someNameForIndex--)
{
Console.WriteLine($"i:{someNameForIndex}, myList[{someNameForIndex}]={myList[someNameForIndex]}");
}
This generates the following output
i:4, myList[4]=E
i:3, myList[3]=D
i:3, Seaky peek at the 5th element (index 4): E
i:2, myList[2]=C
i:1, myList[1]=B
i:0, myList[0]=A
First item is myList[0] and is 'A'
Last item is myList[myLIst.Count()-1] ans is 'E'
i:4, myList[4]=E
i:3, myList[3]=D
i:2, myList[2]=C
i:1, myList[1]=B
i:0, myList[0]=A
So I have this homework assignment that requires me to assign output to labels after I compare two arrays. My problem is that after I compare the two arrays, the output I assign is wrong. I'm supposed to out 'Y' if at a specific index of the two arrays are equal and 'N' if they're not equal but every time I run the code, it outputs 'Y' to all the labels no matter what. How can I fix what is being outputted after the comparison?
private void evaluateStudentAnswers()
{
/* Use a "for" loop to cycle through the answerKey[] and studentAnswers[] arrays, and compare the answers
* in the two arrays at each index. If they match, then increment the global variable "correctAnswers"
* and assign the value 'Y' to the corresponding index in the correctOrIncorrect[] array. if they
* don't match, then increment the global variable "incorrectAnswers" and assign the value 'N' to the
* corresponding indes in the correctOrIncorrec[] array. These two variables will be used to calculate
* the grade percentage.
*/
for (int i = 0; i < studentAnswers.Length; i++)
{
for(int j = 0; j < answerKey.Length; j++)
{
// I think the indexes below are being checked if they're the same and I need to make sure not just the
//indexes are the same but the values as well
if (studentAnswers[i] == answerKey[j])
{
correctAnswers++;
for(int k = 0; k < correctOrIncorrect.Length; k++)
{
correctOrIncorrect[k] = 'Y';
}
}
else
{
incorrectAnswers++;
for (int k = 0; k < correctOrIncorrect.Length; k++)
{
correctOrIncorrect[k] = 'N';
}
}
}
}
}
I think your code can be simplified quite a lot. assuming there's a 1-1 mapping between studentAnswers and answerKey.
for (int i = 0; i < studentAnswers.Length; i++)
{
var studentAnswer = studentAnswers[i];
var answer = answerKey[i];
if (studentAnswer == answer)
{
++correctAnswers;
correctOrIncorrect[i] = 'Y';
}
else
{
++incorrectAnswers;
correctOrIncorrect[i] = 'N'
}
}
All of the arrays are the same size. So when we loop over each answer the student provided, we know we can find the corresponding correct answer in answerKey. Also, the tracking of correct answers also follows the same pattern, for each studentAnswer, we want to record the correctness in correctOrIncorrect, which corresponds to the particular answer the student provided. As such, we only need to perform a single loop, since the i refers to the appropriate index in all the arrays as we're processing.
If studentAnswers.Length == answerKey.Length == correctOrIncorrect.Length
Then
for (int i = 0; i < studentAnswers.Length; i++)
{
if(studentAnswers[i] == answerKey[j])
{
correctAnswers++;
correctOrIncorrect[k] = 'Y';
}
else
{
incorrectAnswers++;
correctOrIncorrect[k] = 'N';
}
}
Since it is an assignment I wont give an answer :) but since you are stuck I encourage you use the guidance below.
These two are unnecessary in your code
inner for-loop on correctOrIncorrect[]
variable "k", you can use "i" instead for correctOrIncorrect value assignment
Since the arrays have to have the same size/order, you only need to loop through them once. Also I find ternary assignments more clear than if blocks:
Func<bool, int> toInt = (b) => b ? 1 : 0;
for (int i = 0; i < studentAnswers.Length; i++)
{
var studentAnswer = studentAnswers[i];
var answer = answerKey[i];
var isCorrect = studentAnswer == answer;
correctOrIncorrect[i] = isCorrect ? 'Y' : 'N';
correctAnswers = isCorrect ? 1 : 0; // toInt(isCorrect)
incorrectAnswers = !isCorrect ? 1 : 0; // toInt(!isCorrect)
}
}
Or in LINQ (just because it's worth learning, but probably not appropriate for homework):
correctOrIncorrect = answerKey.Zip(studentAnswer, (a,b) => a == b ? "Y" : "N").ToArray();
incorrectAnswers = correctOrIncorrect.Count(x => x == "Y");
...
I have a list with several columns. I need to create an ID for a block when my Column1="AA". If a previous block contains an ID, I should have ID+1.
I have something like this:
Column0|Column1|
23|AA
23|AA
23|AX
23|AX
23|AX
23|AA
23|AA
23|AX
23|AA
And I need something like this:
Column0|Column1|Column2
23|AA|1
23|AA|1
23|AX|
23|AX|
23|AX|
23|AA|2
23|AA|2
23|AX|
23|AA|3
In different words, I wanna create IDs (in seq.) to identify blocks of information that contain Column1=AA.
Side note: The order from the list is already the one that I needed.
So, should I use foreach or for loop? I am getting confused when I try to apply my ideas:
(_gDataID is my list; Columns Type will contain my AA or AX or ... ; SeqNumberOfTempCycle is the column that I wanna set with the "ID block" )
int lastseq = 0;
for (int i = 0; i < _gDataID.Count; i++)
{
if (_gDataID[i].Type.ToString() == "AA")
{
//Does the previous columns has a seq?
if (_gDataID[i-1].SeqNumberOfTempCycle.ToString() == null)
{
_gDataID[i].SeqNumberOfTempCycle = lastseq + 1;
lastseq = lastseq + 1;
}
else
{
_gDataID[i].SeqNumberOfTempCycle = lastseq;
}
}
}
As you may notice, my ideas are not working well. First, I cannot do this:
_gDataID[i].SeqNumberOfTempCycle = lastseq + 1;
And my for loop is not looping and setting up the field properly.
If I understand correctly, you need to update counter if there are gaps between the sequence of tokens. In that case, Use Dictionary to remember previously encountered token:
Dictionary<string, int> tokens = new Dictionary<string, int>();
int i = 0;
while(i < gDataID.Count)
{
string dataToken = gDataID[i].Type.ToString();
if(!tokens.ContainsKey(dataToken)
{
tokens.Add(dataToken, 0);
}
tokens[dataToken]++;
While(i < gDataID.Count && gDataID[i].Type.ToString() == dataToken)
{
gDataID[i].SeqNumberOfTempCycle = tokens[dataToken];
i++;
}
}
i have a string that conatin 5 numbers like
'1,4,14,32,47'
i want to make from this string 5 strings of 4 number in each one
like :
'1,4,14,32'
'1,4,14,47'
'1,4,32,47'
'1,14,32,47'
'4,14,32,47'
what is the simple/faster way to do it
is the way of convert this to array unset every time diffrent entery and combine
them back to string ?
is there a simple way to do it ?
thanks
How about something like
string s = "1,4,14,32,47";
string r = String.Join(",", s.Split(',').Where((x, index) => index != 1).ToArray());
Using string.Split() you can create a string array. Loop through it, so that in each loop iteration you indicate which element should be skipped (on the first pass, ignore the first element, on the second pass, ignore the second element).
Inside that loop, create a new array that contains all elements but the one you want to skip, then use string.Join() to create each result.
Have a look at:
http://msdn.microsoft.com/en-us/magazine/ee310028.aspx Here you'll find an example in F# who will give the correct background in combinations and permutations (that's how is called what you need). There is code too, I think it's easy to translate it in C#
Example of Code in C# (text in Italian but code in English)
For those who need a more generic algorithm, here is one which gives n length subsets of m items:
private void GetPermutations()
{
int permutationLength = 4;
string s = "1,4,14,32,47";
string[] subS = s.Split(',');
int[] indexS = new int[permutationLength];
List<string> result = new List<string>();
IterateNextPerm(permutationLength, indexS, subS, result);
// Result will hold all your genberated data.
}
private void IterateNextPerm(int permutationLength, int[] pIndexes, string[] subS, List<string> result)
{
int maxIndexValue = subS.Count() - 1;
bool isCorrect = true;
for (int index = 0; index < permutationLength - 1; index++)
{
if (pIndexes[index] >= pIndexes[index + 1])
{
isCorrect = false;
break;
}
}
// Print result if correct
if (isCorrect)
{
string strNewPermutation = string.Empty;
for (int index = 0; index < permutationLength; index++)
{
strNewPermutation += subS[pIndexes[index]] + ",";
}
result.Add(strNewPermutation.TrimEnd(','));
}
// Increase last index position
pIndexes[permutationLength - 1]++;
// Check and fix if it's out of bounds
if (pIndexes[permutationLength - 1] > maxIndexValue)
{
int? lastIndexIncreased = null;
// Step backwards and increase indexes
for (int index = permutationLength - 1; index > 0; index--)
{
if (pIndexes[index] > maxIndexValue)
{
pIndexes[index - 1]++;
lastIndexIncreased = index - 1;
}
}
// Normalize indexes array, to prevent unnecessary steps
if (lastIndexIncreased != null)
{
for (int index = (int)lastIndexIncreased + 1; index <= permutationLength - 1; index++)
{
if (pIndexes[index - 1] + 1 <= maxIndexValue)
{
pIndexes[index] = pIndexes[index - 1] + 1;
}
else
{
pIndexes[index] = maxIndexValue;
}
}
}
}
if (pIndexes[0] < maxIndexValue)
{
IterateNextPerm(permutationLength, pIndexes, subS, result);
}
}
I know that it's not the nicest coding, but I've written it right now in the last half an hour so I'm sure there are things to tweek there.
Have fun coding!
var elements = string.Split(',');
var result =
Enumerable.Range(0,elements.Length)
.Reverse()
.Select(
i=>
string.Join(","
Enumerable.Range(0,i).Concat(Enumerable.Range(i+1,elements.Length - i - 1))
.Select(j=>elements[j]).ToArray() // This .ToArray() is not needed in NET 4
)
).ToArray();
your wording is pretty confusing...but the example is clear enough. just split it on commas, then remove one index, then use string.Join(",", list); to put it back together..