using System;
using System.Collections.Generic;
using System.Linq;
internal class Program
{
public static bool Aa(int[] a, int k)
{
for (int i = 1; i < a.Length; i++)
if (a[0] + a[i] == k)
return true;
if (a.Length != 1)
Aa(a.Skip(1), k);
return false;
}
static void Main(string[] args)
{
int[] a = { 1, 2, 3, 4, 2, 3, 2, 1 };
Console.WriteLine(Aa(a, 10));
Console.ReadLine();
}
}
The following build error occurs on the recursive method call Aa(a.Skip(1), k);
Argument 1: cannot convert from 'System.Collections.IEnumerable' to 'int[]'
you need to pass an Array obj to Aa Like this :
a.Skip().ToArray();
Like most LINQ methods,
Skip
is designed to work with enumerables, not arrays.
public static System.Collections.Generic.IEnumerable<TSource> Skip<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, int count);
It is OK to pass in an array, but it will implicitly be
upcast
to the more generalized type
IEnumerable,
and that is also the type that will be returned by Skip.
int[] whatGoesIn = {1, 2, 3};
IEnumerable<int> whatComesOut = whatGoesIn.Skip(1);
You cannot safely
downcast
the return value to int[].
As proposed by others, LINQ has a convenient method
ToArray,
but think twice before using it.
The method will create a completely new array object, which is often a total waste of memory as well as CPU time.
Only use this method
when you really need an array.
In your case, ToArray would have to be called once for every element of the original array.
This will put a lot of strain on the heap.
With a big array, you will be seeing a lot of GC.
Make up your mind: either use Skip, or use arrays. Don't do both.
Option 1: Skip, without arrays
Follow the LINQ philosophy and use enumerables all the way.
This has the advantage that it will work on any enumerable: arrays, collections, lists, dictionaries...
So instead of declaring parameter a as an array:
public static bool Aa(int[] a, int k)
declare a as an enumerable:
public static bool Aa(IEnumerable<int> a, int k)
Notice this will immediately eliminate your error. It will introduce a few new ones though. Like in the for loop; IEnumerable<int> has no property Length.
for (int i = 1; i < a.Length; i++)
if (a[0] + a[i] == k)
return true;
Upon close inspection, you are basically looking for an array element that equals k - a[0]. Just use
Contains:
bool found = a.Skip(1).Contains(k - a.First());
if (found) return true;
Another reference to Length:
if (a.Length != 1)
Aa(a.Skip(1), k);
return false;
That's weird; you call Aa but don't do anything with its return value. You probably meant this:
if (a.Length != 1)
return Aa(a.Skip(1), k);
return false;
I will not use Count,
as it is potentially expensive on long enumerables.
I am not actually interested in the exact length; we can stop counting after the second element.
return a.Skip(1).Any() && Aa(a.Skip(1), k);
After refactoring, the whole function becomes a one-liner:
public static bool Aa(IEnumerable<int> a, int k)
{
return a.Skip(1).Contains(k - a.First()) || (a.Skip(1).Any() && Aa(a.Skip(1), k));
}
I'd recommend to make the function robust against zero-length arrays by moving the 'Any' check to the front.
public static bool Aa(IEnumerable<int> a, int k)
{
return a.Any() && (a.Skip(1).Contains(k - a.First()) || Aa(a.Skip(1), k));
}
Option 2: arrays, without Skip
Arrays have one big advantage over enumerables: they are fast.
OP's for loop is faster than my call to Contains.
There is no need to use Skip; just start iterating at a different index.
public static bool Aa(int[] a, int k, int start = 0)
{
for (int i = start + 1; i < a.Length; i++)
if (a[start] + a[i] == k)
return true;
if (start < a.Length)
return Aa(a, k, start + 1);
return false;
}
This is twice as fast as the ToArray solution, and three times as fast as enumerables.
Note
I'm not too thrilled about the use of recursion here,
because nesting depth is proportional to array length.
For long arrays, this may cause a stack overflow.
In theory, the compiler could optimize away the tail recursion, but even in .NET 6, it doesn't
(although this answer suggests otherwise).
Related
Let's say we want to implement a sum algorithm I use C# as an illustration here:
// Iterative
int sum(int[] array) {
int result = 0;
foreach(int item in array) {
result += item;
}
return item;
}
which is equivalent to
// Recursive
int sum(int[] array) {
if(array.Length == 0) {
return 0;
}
// suppose there is a SubArray function here
return array[0] + sum(array.SubArray(1));
}
However, if we want to add a condition to the algorithm where we don't want to add the integer at index 2 to our result, we only need to add one conditional statement to our first (iterative) implementation.
Q: Is there any adaptation to our recursive one to make it work?
The recursive version is inefficient due to the repeated SubArray calls, making the time complexity O(n2). You can re-write this function to accept an additional index parameter, which also happens to be how you can implement skipping a particular index (or set of indices, if you choose).
In C#:
private static int SumSkipIndex(int[] arr, int skip, int i)
{
if (i >= arr.Length) return 0;
return (i == skip ? 0 : arr[i]) + SumSkipIndex(arr, skip, i + 1);
}
If you don't like the added i parameter which changes the function header, just write a separate private recursive "helper" function that can be called from the wrapper with your preferred header.
I'm also assuming you don't wish to hardcode index 2 into the algorithm (if you do, remove the skip parameter and replace i == skip with i == 2).
using System;
class MainClass
{
private static int SumSkipIndex(int[] arr, int skip, int i)
{
if (i >= arr.Length) return 0;
return (i == skip ? 0 : arr[i]) + SumSkipIndex(arr, skip, i + 1);
}
public static int SumSkipIndex(int[] arr, int skip)
{
return SumSkipIndex(arr, skip, 0);
}
public static void Main(string[] args)
{
Console.WriteLine(SumSkipIndex(new int[]{16, 11, 23, 3}, 1)); // => 42
}
}
Lastly, bear in mind that recursion is a terrible choice for this sort of algorithm (summing an array), even with the index version. We have to call a new function just to handle one number, meaning we have a lot of call overhead (allocating stack frames) and can easily blow the stack if the list is too long. But I'm assuming this is just a learning exercise.
A consise solution can be done in C# 8 using array slices.
public static int SumArray(int[] arr, int exclude){
if(arr.Length == 0){
return 0;
}
return (exclude==0?0:arr[0]) + SumArray(arr[1..], exclude-1);
}
The ternary operator checks if the skip index is 0, and if it isn't it will decrement the skip index for the next recursive call. The array is reduced using the slice, which should be more performant than SubArray. (Someone fact check me on the latter)
EDIT: As the other answer has suggested, this causes a bloating of stack frames due to a lack of tail call recursion. The below solution would mitigate the issue by using tail call optimisation, adding the sum variable to the function instead. This means the recursive call can use the same stack frame rather than creating a new one to await the return value before completing the sum.
public static int SumArray(int[] arr, int exclude, int sum=0){
if(arr.Length == 0){
return sum;
}
return SumArray(arr[1..], exclude-1, sum + (exclude==0?0: arr[0]));
}
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the < operand.
public object[] mergeTwoSorted<Tone, Ttwo>(Tone[] array, Ttwo[] array2)
{
object[] mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Any idea on how to tackle this problem?
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object[] MergeTwoSorted<TOne, TTwo> (
TOne[] items1,
TTwo[] items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object[] merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?
Can you fix the bug and finish it off?
Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
public static object[] mergeTwoSorted<Tone, Ttwo>(Tone[] array, Ttwo[] array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable[] mergeTwoSorted<Tone, Ttwo> (Tone[] array, Ttwo[] array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable[] mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone[] mergeTwoSorted<Tone> (Tone[] array, Tone[] array2)
{
IMergeable[] mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Is there a simple^ way of getting the value 'null' if an array element does not exist?
For example, in the code below sArray has 3 elements and the first 3 calls to SomeMethod work (prints true), however the 4th call SomeMethod(sArray[3]); gives me an IndexOutOfRangeException. Is there a way to make the 4th call to SomeMethod print false?
static void Main(string[] args)
{
int[] sArray = new int[]{1,2,3};
SomeMethod(sArray[0]);
SomeMethod(sArray[1]);
SomeMethod(sArray[2]);
SomeMethod(sArray[3]);
}
static void SomeMethod(int? s) => Console.WriteLine(s.HasValue);
^Would prefer single line expression
There is a Linq method ElementAtOrDefault
To use it the way you want to (returning null) you will need ti change the underlying type of your array to nullable int:
int?[] sArray = new int?[]{1,2,3};
SomeMethod(sArray.ElementAtOrDefault(1000));
How about an extension method?
public static T? TryGet<T>(this T[] source, int index) where T: struct
{
if (0 <= index && index < source.Length)
{
return source[index];
}
else
{
return null;
}
}
Then you could write:
static void Main(string[] args)
{
int[] sArray = new int[]{1,2,3};
SomeMethod(sArray.TryGet(0));
SomeMethod(sArray.TryGet(1));
SomeMethod(sArray.TryGet(2));
SomeMethod(sArray.TryGet(3));
}
SomeMethod(sArray.Skip(3).Select(z => (int?)z).FirstOrDefault());
is a working replacement of:
SomeMethod(sArray[3]);
The former will call SomeMethod with null (while the latter will throw an exception if the array doesn't have at least 4 entries).
In Skip(3) the 3 can be changed to whatever index you want to retrieve from the array. The Select is needed to project the int into a int? so that FirstOrDefault returns either the 4th element or null.
If you don't want to use LINQ then you could use:
SomeMethod(sArray.Length > 3 ? sArray[3] : (int?)null);
instead.
Or consider using:
foreach (var entry in sArray.Take(4))
{
SomeMethod(entry);
}
to loop through up to 4 elements of the array (it will work fine if there are fewer than 4 - it will just make fewer calls to SomeMethod).
Arrays in C# have a .Length property which you can check before trying to pass an item from one to SomeMethod, and the typical approach is to loop through each element of the array rather than guessing whether or not an index is valid:
for (int i = 0; i < sArray.Length; i++)
{
SomeMethod(sArray[i]);
}
You will not be able to avoid an IndexOutOfRangeException if you reference an index in an array that doesn't exist.
However, if you really want a method with this type of functionality, you could simply modify your existing code to check whether or not the index specified is greater than the length of the array.
Since your array is an int[] (and not an int?[]), all valid indexes will have a value. Also, we can use the ?. to handle cases where the array itself may be null:
private static void SomeMethod(int[] array, int index) =>
Console.WriteLine(index >= 0 && index < array?.Length);
Then in use, instead of passing an array item with an invalid index (which will always throw an IndexOutOfRangeException), you would pass the array itself and the index separately:
static void Main()
{
int[] sArray = new int[] { 1, 2, 3 };
SomeMethod(sArray, 0);
SomeMethod(sArray, 1);
SomeMethod(sArray, 2);
SomeMethod(sArray, 3);
SomeMethod(null, 0);
GetKeyFromUser("\nPress any key to exit...");
}
Output
in this case I'll suggest you to create a extension somewhere in your code like this
static class ArrExt
{
public static int? Get(this int[] arr, int i)
{
return (i >= 0 && i < arr.Length) ? arr[i] : default(int?);
}
}
then you can do this
int[] sArray = new int[] { 1, 2, 3 };
SomeMethod(sArray.Get(0));
SomeMethod(sArray.Get(1));
SomeMethod(sArray.Get(2));
SomeMethod(sArray.Get(3));
okay this is not a single line solution I know, but it's easier for both programmer and computer.
Let say I got this function :
void int Calculate(double[] array) {}
And in my main I got this array:
double[,] myArray = new double[3,3];
How can I call Calculate(...) ?
I try (that's don't compile) :
double[] mySingleArray = myArray[0];
What I want to avoid is unnecessary loop (for).
I declare a regular array, but if a jagged array or any other type of array works better, it's fine for me.
I use c# 3.5
First, let's declare your Calculate() method like this:
int Calculate(IEnumerable<double> doubles)
Don't worry, you can still pass an array to that code. You might also need IList<double>, but 9 times out of 10 the IEnumerable is good enough. The main thing is that this will let us use the yield keyword to slice up your array in an efficient way:
public static IEnumerable<T> Slice(this T[,] values)
{
return Slice(values, 0, 0);
}
public static IEnumerable<T> Slice(this T[,] values, int index)
{
return Slice(values, 0, index);
}
public static IEnumerable<T> Slice(this T[,] values, int dimension, int index)
{
int length = values.GetUpperBound(dimension);
int[] point = new int[values.Rank];
point[dimension] = index;
dimension = 1 - dimension;// only works for rank == 2
for (int i = 0; i < length; i++)
{
point[dimension] = i;
yield return (T)values.GetValue(point);
}
}
It still needs some work because it only works with rank 2 arrays, but it should be fine for the example you posted.
Now you can call your calculate function like this:
Calculate(myArray.Slice(0));
Note that due to the way IEnumerable and the yield statement work the for loop in the code I posted is essentially free. It won't run until you actually iterate the items in your Calculate method, and even there runs in a "just-in-time" fashion so that the whole algorithm remains O(n).
It gets even more interesting when you share what your Calculate method is doing. You might be able to express it as a simple Aggregate + lambda expression. For example, let's say your calculate method returned the number of items > 5:
myArray.Slice(0).Count(x => x > 5);
Or say it summed all the items:
myArray.Slice().Sum();
A jagged array works the way you want:
double[][] jaggedArray = new double[][100];
for (int i = 0; i < jaggedArray.Length; ++i)
jaggedArray[i] = new double[100];
myFunction(jaggedArray[0]);
You can have different sizes for each array in this way.
A jagged array would let you split out the first array!
The Slice() method given above will get you a single row from your array, which seems to match the sample given in your question.
However, if you want a one dimensional array that contains all the elements in the rectangular array, you can use something like this, which is also O(n).
public static T[] Flatten<T>(this T[,] array)
where T : struct
{
int size = Marshal.SizeOf(array[0, 0]);
int totalSize = Buffer.ByteLength(array);
T[] result = new T[totalSize / size];
Buffer.BlockCopy(array, 0, result, 0, totalSize);
return result;
}
I need to move backwards through an array, so I have code like this:
for (int i = myArray.Length - 1; i >= 0; i--)
{
// Do something
myArray[i] = 42;
}
Is there a better way of doing this?
Update: I was hoping that maybe C# had some built-in mechanism for this like:
foreachbackwards (int i in myArray)
{
// so easy
}
While admittedly a bit obscure, I would say that the most typographically pleasing way of doing this is
for (int i = myArray.Length; i --> 0; )
{
//do something
}
In C++ you basicially have the choice between iterating using iterators, or indices.
Depending on whether you have a plain array, or a std::vector, you use different techniques.
Using std::vector
Using iterators
C++ allows you to do this using std::reverse_iterator:
for(std::vector<T>::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
/* std::cout << *it; ... */
}
Using indices
The unsigned integral type returned by `std::vector::size` is *not* always `std::size_t`. It can be greater or less. This is crucial for the loop to work.
for(std::vector<int>::size_type i = someVector.size() - 1;
i != (std::vector<int>::size_type) -1; i--) {
/* std::cout << someVector[i]; ... */
}
It works, since unsigned integral types values are defined by means of modulo their count of bits. Thus, if you are setting -N, you end up at (2 ^ BIT_SIZE) -N
Using Arrays
Using iterators
We are using `std::reverse_iterator` to do the iterating.
for(std::reverse_iterator<element_type*> it(a + sizeof a / sizeof *a), itb(a);
it != itb;
++it) {
/* std::cout << *it; .... */
}
Using indices
We can safely use `std::size_t` here, as opposed to above, since `sizeof` always returns `std::size_t` by definition.
for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
/* std::cout << a[i]; ... */
}
Avoiding pitfalls with sizeof applied to pointers
Actually the above way of determining the size of an array sucks. If a is actually a pointer instead of an array (which happens quite often, and beginners will confuse it), it will silently fail. A better way is to use the following, which will fail at compile time, if given a pointer:
template<typename T, std::size_t N> char (& array_size(T(&)[N]) )[N];
It works by getting the size of the passed array first, and then declaring to return a reference to an array of type char of the same size. char is defined to have sizeof of: 1. So the returned array will have a sizeof of: N * 1, which is what we are looking for, with only compile time evaluation and zero runtime overhead.
Instead of doing
(sizeof a / sizeof *a)
Change your code so that it now does
(sizeof array_size(a))
I would always prefer clear code against 'typographically pleasing' code.
Thus, I would always use :
for (int i = myArray.Length - 1; i >= 0; i--)
{
// Do something ...
}
You can consider it as the standard way to loop backwards.
Just my two cents...
In C#, using Visual Studio 2005 or later, type 'forr' and hit [TAB] [TAB]. This will expand to a for loop that goes backwards through a collection.
It's so easy to get wrong (at least for me), that I thought putting this snippet in would be a good idea.
That said, I like Array.Reverse() / Enumerable.Reverse() and then iterate forwards better - they more clearly state intent.
In C# using Linq:
foreach(var item in myArray.Reverse())
{
// do something
}
That's definitely the best way for any array whose length is a signed integral type. For arrays whose lengths are an unsigned integral type (e.g. an std::vector in C++), then you need to modify the end condition slightly:
for(size_t i = myArray.size() - 1; i != (size_t)-1; i--)
// blah
If you just said i >= 0, this is always true for an unsigned integer, so the loop will be an infinite loop.
Looks good to me. If the indexer was unsigned (uint etc), you might have to take that into account. Call me lazy, but in that (unsigned) case, I might just use a counter-variable:
uint pos = arr.Length;
for(uint i = 0; i < arr.Length ; i++)
{
arr[--pos] = 42;
}
(actually, even here you'd need to be careful of cases like arr.Length = uint.MaxValue... maybe a != somewhere... of course, that is a very unlikely case!)
The best way to do that in C++ is probably to use iterator (or better, range) adaptors, which will lazily transform the sequence as it is being traversed.
Basically,
vector<value_type> range;
foreach(value_type v, range | reversed)
cout << v;
Displays the range "range" (here, it's empty, but i'm fairly sure you can add elements yourself) in reverse order.
Of course simply iterating the range is not much use, but passing that new range to algorithms and stuff is pretty cool.
This mechanism can also be used for much more powerful uses:
range | transformed(f) | filtered(p) | reversed
Will lazily compute the range "range", where function "f" is applied to all elements, elements for which "p" is not true are removed, and finally the resulting range is reversed.
Pipe syntax is the most readable IMO, given it's infix.
The Boost.Range library update pending review implements this, but it's pretty simple to do it yourself also. It's even more cool with a lambda DSEL to generate the function f and the predicate p in-line.
In C I like to do this:
int i = myArray.Length;
while (i--) {
myArray[i] = 42;
}
C# example added by MusiGenesis:
{int i = myArray.Length; while (i-- > 0)
{
myArray[i] = 42;
}}
I prefer a while loop. It's more clear to me than decrementing i in the condition of a for loop
int i = arrayLength;
while(i)
{
i--;
//do something with array[i]
}
i do this
if (list.Count > 0)
for (size_t i = list.Count - 1; ; i--)
{
//do your thing
if (i == 0) //for preventing unsigned wrap
break;
}
but for some reason visual studio 2019 gets angry and warns me "ill-defined loop" or something.. it doesnt trust me
edit: you can remove "i >= 0" from "for (size_t i = list.Count - 1; i >= 0; i--)" .. its unnecessary
I'm going to try answering my own question here, but I don't really like this, either:
for (int i = 0; i < myArray.Length; i++)
{
int iBackwards = myArray.Length - 1 - i; // ugh
myArray[iBackwards] = 666;
}
I'd use the code in the original question, but if you really wanted to use foreach and have an integer index in C#:
foreach (int i in Enumerable.Range(0, myArray.Length).Reverse())
{
myArray[i] = 42;
}
// this is how I always do it
for (i = n; --i >= 0;){
...
}
For C++:
As mentioned by others, when possible (i.e. when you only want each element at a time) it is strongly preferable to use iterators to both be explicit and avoid common pitfalls. Modern C++ has a more concise syntax for that with auto:
std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
std::cout<<*it<<" ";
}
prints 4 3 2 1 .
You can also modify the value during the loop:
std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
*it = *it + 10;
std::cout<<*it<<" ";
}
leading to 14 13 12 11 being printed and {11, 12, 13, 14} being in the std::vector afterwards.
If you don't plan on modifying the value during the loop, you should make sure that you get an error when you try to do that by accident, similarly to how one might write for(const auto& element : vec). This is possible like this:
std::vector<int> vec = {1,2,3,4};
for (auto it = vec.crbegin(); it != vec.crend(); ++it) { // used crbegin()/crend() here...
*it = *it + 10; // ... so that this is a compile-time error
std::cout<<*it<<" ";
}
The compiler error in this case for me is:
/tmp/main.cpp:20:9: error: assignment of read-only location ‘it.std::reverse_iterator<__gnu_cxx::__normal_iterator<const int*, std::vector<int> > >::operator*()’
20 | *it = *it + 10;
| ~~~~^~~~~~~~~~
Also note that you should make sure not to use different iterator types together:
std::vector<int> vec = {1,2,3,4};
for (auto it = vec.rbegin(); it != vec.end(); ++it) { // mixed rbegin() and end()
std::cout<<*it<<" ";
}
leads to the verbose error:
/tmp/main.cpp: In function ‘int main()’:
/tmp/main.cpp:19:33: error: no match for ‘operator!=’ (operand types are ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >’ and ‘std::vector<int>::iterator’ {aka ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’})
19 | for (auto it = vec.rbegin(); it != vec.end(); ++it) {
| ~~ ^~ ~~~~~~~~~
| | |
| | std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}
| std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >
If you have C-style arrays on the stack, you can do things like this:
int vec[] = {1,2,3,4};
for (auto it = std::crbegin(vec); it != std::crend(vec); ++it) {
std::cout<<*it<<" ";
}
If you really need the index, consider the following options:
check the range, then work with signed values, e.g.:
void loop_reverse(std::vector<int>& vec) {
if (vec.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
throw std::invalid_argument("Input too large");
}
const int sz = static_cast<int>(vec.size());
for(int i=sz-1; i >= 0; --i) {
// do something with i
}
}
Work with unsigned values, be careful, and add comments, e.g.:
void loop_reverse2(std::vector<int>& vec) {
for(size_t i=vec.size(); i-- > 0;) { // reverse indices from N-1 to 0
// do something with i
}
}
calculate the actual index separately, e.g.:
void loop_reverse3(std::vector<int>& vec) {
for(size_t offset=0; offset < vec.size(); ++offset) {
const size_t i = vec.size()-1-offset; // reverse indices from N-1 to 0
// do something with i
}
}
If you use C++ and want to use size_t, not int,
for (size_t i = yourVector.size(); i--;) {
// i is the index.
}
(Note that -1 is interpreted as a large positive number if it's size_t, thus a typical for-loop such as for (int i = yourVector.size()-1; i>=0; --i) doesn't work if size_t is used instead of int.)
Not that it matters after 13+ years but just for educational purposes and a bit of trivial learning;
The original code was;
for (int i = myArray.Length - 1; i >= 0; i--)
{
// Do something
myArray[i] = 42;
}
You don't really need to test 'i' again being greater or equal to zero since you simply need to only produce a 'false' result to terminate the loop. Therefore, you can simple do this where you are only testing 'i' itself if it is true or false since it will be (implicitly) false when it hits zero.;
for (int i = myArray.Length - 1; i; i--)
{
// Do something
myArray[i] = 42;
}
Like I stated, it doesn't really matter, but it is just interesting to understand the mechanics of what is going on inside the for() loop.
NOTE: This post ended up being far more detailed and therefore off topic, I apologize.
That being said my peers read it and believe it is valuable 'somewhere'. This thread is not the place. I would appreciate your feedback on where this should go (I am new to the site).
Anyway this is the C# version in .NET 3.5 which is amazing in that it works on any collection type using the defined semantics. This is a default measure (reuse!) not performance or CPU cycle minimization in most common dev scenario although that never seems to be what happens in the real world (premature optimization).
*** Extension method working over any collection type and taking an action delegate expecting a single value of the type, all executed over each item in reverse **
Requres 3.5:
public static void PerformOverReversed<T>(this IEnumerable<T> sequenceToReverse, Action<T> doForEachReversed)
{
foreach (var contextItem in sequenceToReverse.Reverse())
doForEachReversed(contextItem);
}
Older .NET versions or do you want to understand Linq internals better? Read on.. Or not..
ASSUMPTION: In the .NET type system the Array type inherits from the IEnumerable interface (not the generic IEnumerable only IEnumerable).
This is all you need to iterate from beginning to end, however you want to move in the opposite direction. As IEnumerable works on Array of type 'object' any type is valid,
CRITICAL MEASURE: We assume if you can process any sequence in reverse order that is 'better' then only being able to do it on integers.
Solution a for .NET CLR 2.0-3.0:
Description: We will accept any IEnumerable implementing instance with the mandate that each instance it contains is of the same type. So if we recieve an array the entire array contains instances of type X. If any other instances are of a type !=X an exception is thrown:
A singleton service:
public class ReverserService
{
private ReverserService() { }
/// <summary>
/// Most importantly uses yield command for efficiency
/// </summary>
/// <param name="enumerableInstance"></param>
/// <returns></returns>
public static IEnumerable ToReveresed(IEnumerable enumerableInstance)
{
if (enumerableInstance == null)
{
throw new ArgumentNullException("enumerableInstance");
}
// First we need to move forwarad and create a temp
// copy of a type that allows us to move backwards
// We can use ArrayList for this as the concrete
// type
IList reversedEnumerable = new ArrayList();
IEnumerator tempEnumerator = enumerableInstance.GetEnumerator();
while (tempEnumerator.MoveNext())
{
reversedEnumerable.Add(tempEnumerator.Current);
}
// Now we do the standard reverse over this using yield to return
// the result
// NOTE: This is an immutable result by design. That is
// a design goal for this simple question as well as most other set related
// requirements, which is why Linq results are immutable for example
// In fact this is foundational code to understand Linq
for (var i = reversedEnumerable.Count - 1; i >= 0; i--)
{
yield return reversedEnumerable[i];
}
}
}
public static class ExtensionMethods
{
public static IEnumerable ToReveresed(this IEnumerable enumerableInstance)
{
return ReverserService.ToReveresed(enumerableInstance);
}
}
[TestFixture]
public class Testing123
{
/// <summary>
/// .NET 1.1 CLR
/// </summary>
[Test]
public void Tester_fornet_1_dot_1()
{
const int initialSize = 1000;
// Create the baseline data
int[] myArray = new int[initialSize];
for (var i = 0; i < initialSize; i++)
{
myArray[i] = i + 1;
}
IEnumerable _revered = ReverserService.ToReveresed(myArray);
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_why_this_is_good()
{
ArrayList names = new ArrayList();
names.Add("Jim");
names.Add("Bob");
names.Add("Eric");
names.Add("Sam");
IEnumerable _revered = ReverserService.ToReveresed(names);
Assert.IsTrue(TestAndGetResult(_revered).Equals("Sam"));
}
[Test]
public void tester_extension_method()
{
// Extension Methods No Linq (Linq does this for you as I will show)
var enumerableOfInt = Enumerable.Range(1, 1000);
// Use Extension Method - which simply wraps older clr code
IEnumerable _revered = enumerableOfInt.ToReveresed();
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_linq_3_dot_5_clr()
{
// Extension Methods No Linq (Linq does this for you as I will show)
IEnumerable enumerableOfInt = Enumerable.Range(1, 1000);
// Reverse is Linq (which is are extension methods off IEnumerable<T>
// Note you must case IEnumerable (non generic) using OfType or Cast
IEnumerable _revered = enumerableOfInt.Cast<int>().Reverse();
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_final_and_recommended_colution()
{
var enumerableOfInt = Enumerable.Range(1, 1000);
enumerableOfInt.PerformOverReversed(i => Debug.WriteLine(i));
}
private static object TestAndGetResult(IEnumerable enumerableIn)
{
// IEnumerable x = ReverserService.ToReveresed(names);
Assert.IsTrue(enumerableIn != null);
IEnumerator _test = enumerableIn.GetEnumerator();
// Move to first
Assert.IsTrue(_test.MoveNext());
return _test.Current;
}
}