Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I had a programming exam where at the end, I always had an IndexOutOfRangeException for the code below (for the if statement, exactly).
The task was to remove numbers in 21..32 range from the list then print out the new list. nums is a List<int> with exactly 6 numbers given by the user.
I've been programming for 4 years now and I can't find a single problem :D
Here's the code.
// nums is a List<int> with exactly 6 elements in it.
List<int> changedNums = new List<int>(nums);
for (int k = 0; k < 6; k++)
if (changedNums[k] >= 21 && changedNums[k] <= 32)
changedNums.RemoveAt(k);
I didn't put brackets here because it's a one-liner.
The issue here is that you modifying the length of the list while iterating. After you deleted at least one item from changedNums list, its length is less than the initial 6 (so you get IndexOutOfRangeException). Also, once you deleted k-th item, you should decrement k. I modified your sample code to work as follows:
static void Main()
{
List<int> nums = new List<int>() { 1, 22, 30, 4, 5, 6 };
List<int> changedNums = new List<int>(nums);
var currentLength = changedNums.Count;
for (int k = 0; k < currentLength; k++)
{
if (changedNums[k] >= 21 && changedNums[k] <= 32)
{
changedNums.RemoveAt(k);
--k;
--currentLength;
}
}
Console.WriteLine(string.Join(" ", changedNums));
}
This will print: 1 4 5 6
Edit:
As pointed by #derpirscher and #Jon Skeet in comments, index manipulations can be easily avoided by iterating the array from end to start:
List<int> nums = new List<int>() { 1, 22, 30, 4, 5, 6 };
List<int> changedNums = new List<int>(nums);
for (int k = changedNums.Count - 1; k >= 0 ; k--)
if (changedNums[k] >= 21 && changedNums[k] <= 32)
changedNums.RemoveAt(k);
Console.WriteLine(string.Join(" ", changedNums));
An even easier solution to your problem can be achieved using LINQ:
var changedNums = nums.Where(num => num < 21 || num > 32).ToList();
All the solutions will produce the same result 1 4 5 6
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm facing a problem when trying to play with C# list. Currently I have a list of integer. And I'm looking for a way to sum up every 5 integer, until the end of the list.
For example I have a list like this:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
How to sum up every N elements (let's say 5) in the list and become:
[ 15, 40 ]
FYI, the list consist of hundred and thousand int elements.
Thanks.
Since noone's mentioned the simple way yet...
Note that if the input is not divisible by the group size, any extra elements will be ignored. For example, if the input is 11 elements, and the group size is 5, this will give 2 sums of 5 elements and then ignore the 11th input element.
public static int[] SumEvery(int[] input, int groupSize)
{
// The number of groups we have
int numGroups = input.Length / groupSize;
int[] result = new int[numGroups];
// For each group of numbers...
for (int group = 0; group < numGroups; group++)
{
// ... loop through each number in that group, adding to the sum ...
int sum = 0;
for (int i = 0; i < groupSize; i++)
{
sum += input[group * groupSize + i];
}
// ... then store that sum in our array of results
result[group] = sum;
}
return result;
}
int[] input = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] result = SumEvery(input, 5);
If you want to stream the results as an IEnumerable<int>, rather than collecting them all into an array, then:
public static IEnumerable<int> SumEvery(int[] input, int groupSize)
{
int numGroups = input.Length / groupSize;
for (int group = 0; group < numGroups; group++)
{
int sum = 0;
for (int i = 0; i < groupSize; i++)
{
sum += input[group * groupSize + i];
}
yield return sum;
}
}
You could do this with a bit of Linq
var ints = new []{1,2,3,4,5,6,7,8,9,10};
var result = ints.Select((x,i) => new{Num = x,Index = i}) // Project to a list with the index and number
.GroupBy (i => i.Index/5) // group by the int division by 5
.Select(g => g.Sum(a => a.Num)); // sum the numbers in each group
Live example: https://dotnetfiddle.net/BabP5N
Note that is is by far the least efficient way - and with a large data set will not perform well. But for a small dataset will work fine. This code is possibly the clearest interpretation of the problem.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
im generating a list of numbers such as 100 101 102 103 110 111 112 130 131 132 and i want to remove numbers that are sequential till the next number but with a specific tolerance...
so with a tolerance of 3 for example my output will be
100 102
110 112
130 132
the tolerance value must be adjustable...
ADRS is my list of int's,
ADRSC is my list of strings after being cleaned
for (int v = 0; v <= ADRS.Count - 2; v++)
{
if (v == 0) //adds first number
ADRSC.Add(ADRS[v].ToString());
if (ADRS[v]-(int.Parse(ADRSC.Last())) > 3)
{
ADRSC.Add(ADRS[v].ToString());
}
}
in short:
i want to remove the numbers inbetween, that have a difference of under 3
This worked
adrCache = Nums.First();
for (int x=1; x < Nums.Count-2; x++)
{
if ((Nums[x+1] - adrCache) <= 4)
{
adrCache = Nums[x+1];
Nums[x] = 0; //ill then just remove all zeros
}
else {
adrCache = Nums[x];
}
}
Here's a shot at what you're looking for, but the question is a little unclear to me:
public static List<int> RemoveSequential(List<int> items, int tolerance)
{
if (items == null || items.Count < 2) return items;
var result = new List<int> {items.First()};
var sequenceCount = 0;
for(int i = 1; i < items.Count; i++)
{
if (Math.Abs(items[i] - items[i - 1]) == 1)
{
sequenceCount++;
if (sequenceCount == tolerance - 1)
{
result.Add(items[i]);
}
}
else
{
sequenceCount = 0;
result.Add(items[i]);
}
}
return result;
}
Usage would look like:
public static void Main(string[] args)
{
var input = new List<int> {100, 101, 102, 103, 110, 111, 112, 130, 131, 132};
var output = RemoveSequential(input, 3);
Console.WriteLine($"Input: {string.Join(", ", input)}");
Console.WriteLine($"Output: {string.Join(", ", output)}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm sure I'm making an incredibly silly mistake but I've been at this for hours and I just want my code to sort prettily... Something is going wrong with implementation when odd numbers come into the equation.
Below is my MergeSplit method:
static List<Motor> MergeSplit(List<int> ListX)
{
int n = ListX.Count;
if (n <= 1)
return ListX;
List<int> left = new List<int>();
List<int> right = new List<int>();
for (int i = 0; i < n; i++)
{
if (i < (n / 2))
left.Add(ListX[i]);
else
right.Add(ListX[i]);
}
left = MergeSplit(left);
right = MergeSplit(right);
return Merge(left, right);
}
And here is the Merge method:
static List<int> Merge(List<int> ListX, List<int> ListY)
{
List<int> result = new List<int>();
int i = 0;
while (ListX.Count > i && ListY.Count > i)
{
if (ListX[i] > ListY[i])
{
result.Add(ListY[i]);
result.Add(ListX[i]);
}
else
{
result.Add(ListX[i]);
result.Add(ListY[i]);
}
i++;
}
//If odd, add the rest to the result
if (ListX.Count > ListY.Count)
result.Add(ListX[ListX.Count - 1]);
else if (ListY.Count > ListX.Count)
result.Add(ListY[ListY.Count - 1]);
return result;
}
Thanks for your help!
Update
The algorithm just doesnt sort correctly with certain inputs
The problem is your Merge routine
You are comparing the left and right and adding them to the list respectively, where you should be comparing the heads, and adding the lowest to the result, and removing that head respectively for the next comparison
This is the pseudo code from wiki https://en.wikipedia.org/wiki/Merge_sort
while left is not empty and right is not empty do
if first(left) ≤ first(right) then
append first(left) to result
left := rest(left)
else
append first(right) to result
right := rest(right)
You can see why thats important here
As you can see its actually comparing the first left and first right, then adding them to the result and removing that item from the list. which is vastly different from what you are doing. you either need 2 index variables, or remove the items from the list
while (listX.Count > 0 && listY.Count > 0)
if (listX[0] > listY[0])
{
result.Add(listY[0]);
listY.RemoveAt(0);
}
else
{
result.Add(listX[0]);
listX.RemoveAt(0);
}
if (listX.Count > 0)
result.AddRange(listX);
else if (listY.Count > 0)
result.AddRange(listY);
Just for fun, i found this was easier to play with queues, they seem to like this sort of thing
private static Queue<int> Merge(Queue<int> left, Queue<int> right)
{
var result = new Queue<int>();
while (left.Count > 0 && right.Count > 0)
result.Enqueue(left.Peek() > right.Peek() ? right.Dequeue() : left.Dequeue());
foreach (var item in left)
result.Enqueue(item);
foreach (var item in right)
result.Enqueue(item);
return result;
}
private static Queue<int> MergeSplit(Queue<int> list)
{
var n = list.Count;
if (n <= 1)
return list;
var left = new Queue<int>();
var right = new Queue<int>();
for (var i = 0; i < n; i++)
if (i < n / 2)
left.Enqueue(list.Dequeue());
else
right.Enqueue(list.Dequeue());
left = MergeSplit(left);
right = MergeSplit(right);
return Merge(left, right);
}
Usage
var list = new List<int> { 8, 7, 6, 4, 43, 23, 435, 76, 7, 7877, 5, 421, 2 };
var results = MergeSplit(new Queue<int>(list));
Console.WriteLine(string.Join(", ", results));
Output
2, 4, 5, 6, 7, 7, 8, 23, 43, 76, 421, 435, 7877
Full Demo Here
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
In my main I have this array with random numbers
static void Main(string[] args)
{
int [] numbers = new int[] { 1, 6, 4, 11, 2, 5, 9, 3, 7, 10, 12, 8 };
Console.WriteLine("The scores are: ");
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
Console.ReadLine();
}
I need to make a static method in a class that would rearrange these numbers so that they are in order and I'm not sure how to do this. I need to swap these numbers.
Use Array.Sort to sort your original array:
Array.Sort(numbers);
Or Enumerable.OrderBy to create new sorted sequence, which you can save to array:
int[] sorted = numbers.OrderBy(i => i).ToArray();
Array class has a Sort method (Array) which takes array as a parameter.
Sorts the elements in an entire one-dimensional Array using the
IComparable implementation of each element of the Array.
Here am example with LINQPad;
void Main()
{
int [] numbers = new int[] { 1, 6, 4, 11, 2, 5, 9, 3, 7, 10, 12, 8 };
ReturnSortedArray(numbers);
foreach (var element in numbers)
{
element.Dump();
}
}
static void ReturnSortedArray(Array a)
{
Array.Sort(a);
}
Output will be;
1
2
3
4
5
6
7
8
9
10
11
12
To answer the question which was how do I create a static method to sort the Array you can use the code below.
public static void Main(string[] args)
{
int[] numbers = new int[] { 1, 6, 4, 11, 2, 5, 9, 3, 7, 10, 12, 8 };
Console.WriteLine ("The scores are: ");
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine (numbers [i]);
}
Console.WriteLine ("The scores in order are: ");
SortArray (numbers);
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine (numbers [i]);
}
Console.ReadLine ();
}
public static int[] SortArray(int[] arrayIn)
{
Array.Sort (arrayIn);
return arrayIn;
}
OUTPUT
The scores are:
1 6 4 11 2 5 9 3 7 10 12 8
The scores in order are:
1 2 3 4 5 6 7 8 9 10 11 12
you can sort in here
Array.Sort(numbers);
Say I have an an array of numbers:
int[] that = new [] {1, 2, 3, 2, 4, 8, 9, 7};
I'm trying to display them so that the numbers that are increasing have their own line.
For example the result would be:
1 2 3
2 4 8 9
7
I'm able to do the first row using,
for (int i = 1; i < that.Length; i++)
{
if (that[i-1] < that[i])
{
Console.Write(that[i-1] + " ");
}
}
The thing is this works for the first row because 1-3 are increasing but stops after that.
I'm not exactly sure how to continue so that 2 4 8 9, then 7 are written.
I have a feeling this is homework so I'm going to leave the actual coding to you. But here's how to do it in plain language:
Have a variable where we store the previous value. Let's call it oldValue, and start it with zero (if you're only using positive numbers in your array).
Go through the array one item at a time.
Check to see if that number is larger than oldValue.
If FALSE, print the new line character. "\n" in C#.
Print that number and make oldValue equal that number.
Unless your numbers are finished get the next number and go to step 3.
You never create a new line.
int[] arr = new[] {1, 2, 3, 2, 4, 8, 9, 7};
for(var i = 0; i < arr.Length; i++){
if(i == 0 || ((i < arr.Length - 1) && arr[i] < arr[i + 1])){
Console.Write(arr[i]);
} else {
Console.Write("{0}\n", arr[i]);
}
}
Output:
123
2489
7
Couple of remarks:
Avoid the usage of this as a variable name. It's a reserved
keyword.
Use \n as a newline character.
There are a number of ways you can do this, either by appending a string with characters until a lesser one is reached and then using the Console.WriteLine() command to write the entire string at once, or (the easier way given your code) which is to simply test for the new value being lesser than the previous and inserting a newline character into your text.
// Start at zero
for (int i = 0; i < this.Length; i++)
{
// If this is not the first element in the array
// and the new element is smaller than the previous
if (i > 0 && this[i] < this[i-1])
{
// Then insert a new line into the output
Console.Write(Environment.NewLine);
}
Console.Write(this[i] + " ");
}
int[] numbers = new int[] { 1, 2, 3, 2, 4, 8, 9, 7 };
String orderedNumbers = String.Empty;
for (int i = 0; i < numbers.Length; i++)
{
if (i == 0 || numbers[i] > numbers[i - 1])
{
orderedNumbers += numbers[i].ToString();
}
else
{
orderedNumbers += System.Environment.NewLine + numbers[i].ToString();
}
}
MessageBox.Show(orderedNumbers);