In C++, we can set a range of values of an array(and other similar containers) using fill.
For example,
fill(number, number+n,10);
The above code will set the first n values of the array number with the value 10.
What is the closest C# equivalent to this.
There's no equivalent method but there are many ways to write similar code
Methods from the Linq-to-Objects classes can create sequences that you can use to initialize lists but this is very different from how things in C++ actually occur.
new List<char>(Enumerable.Repeat('A', 10));
new List<int>(Enumerable.Range(1, 10));
C++ can accomplish these things more generally thanks to how C++ templates work, and while simple type constraints in C# help, they do not offer the same flexibility.
I'm not sure one exists, but you can code your own easily:
void Fill<T>(T[] array, int start, int count, T value)
{
for (int i = start, j = 0; j < count; i++, j++)
array[i] = value;
}
Obviously missing parameter checking, but you get the drill.
There is no direct equivalent, but you can do it in two steps. First use Enumerable.Repeat to create an array with the same value in each element. Then copy that over the destination array:
var t = Enumerable.Repeat(value, count).ToArray();
Array.Copy(t, 0, dest, destStartIndex, count);
For other destination containers there is a lack of an equivalent to Array.Copy, but it is easy to add these as destinations, eg:
static void Overwrite<T>(this List<T> dest, IEnumerable<T> source, int destOffset) {
int pos = destOffset;
foreach (var val in source) {
// Could treat this as an error, or have explicit count
if (pos = dest.Length) { return; }
dest[pos++] = val;
}
}
Related
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;
}
}
I am much more familiar with C# than C++ so I must ask for advice on this issue. I had to rewrite some code pieces to C++ and then (surprisingly) ran into performance issues.
I've narrowed the problem down to these snippets:
C#
public class SuffixTree
{
public class Node
{
public int Index = -1;
public Dictionary<char, Node> Children = new Dictionary<char, Node>();
}
public Node Root = new Node();
public String Text;
public SuffixTree(string s)
{
Text = s;
for (var i = s.Length - 1; i >= 0; --i)
InsertSuffix(s, i);
}
public void InsertSuffix(string s, int from)
{
var cur = Root;
for (int i = from; i < s.Length; ++i)
{
var c = s[i];
if (!cur.Children.ContainsKey(c))
{
var n = new Node() { Index = from };
cur.Children.Add(c, n);
return;
}
cur = cur.Children[c];
}
}
public bool Contains(string s)
{
return FindNode(s) != null;
}
private Node FindNode(string s)
{
var cur = Root;
for (int i = 0; i < s.Length; ++i)
{
var c = s[i];
if (!cur.Children.ContainsKey(c))
{
for (var j = i; j < s.Length; ++j)
if (Text[cur.Index + j] != s[j])
return null;
return cur;
}
cur = cur.Children[c];
}
return cur;
}
}
}
C++
struct node
{
int index;
std::unordered_map<char, node*> children;
node() { this->index = -1; }
node(int idx) { this->index = idx; }
};
struct suffixTree
{
node* root;
char* text;
suffixTree(char* str)
{
int len = strlen(str) + 1;
this->text = new char[len];
strncpy(this->text, str, len);
root = new node();
for (int i = len - 2; i >= 0; --i)
insertSuffix(str, i);
}
void insertSuffix(char* str, int from)
{
node* current = root;
for (int i = from; i < strlen(str); ++i)
{
char key = str[i];
if (current->children.find(key) == current->children.end())
{
current->children[key] = new node(from);
return;
}
current = current->children[key];
}
}
bool contains(char* str)
{
node* current = this->root;
for (int i = 0; i < strlen(str); ++i)
{
char key = str[i];
if (current->children.find(key) == current->children.end())
{
for (int j = i; j < strlen(str); ++j)
if (this->text[current->index + j] != str[j])
return false;
return true;
}
current = current->children[key];
}
}
}
In both cases I'm creating a suffix tree and later using it in a much bigger function which is not relevant for the post (lets call it F()). I've tested both on two randomly generated strings of length 100000. The C# version constructed my suffix tree and used it in F() in a total execution time of: 480 ms while the code which I've "translated to C++" executed in 48 sec
I've drilled this down further and it seems that in my C++ code, the constructor takes 47 sec while using the tree in F() runs at 48 ms which is 10 times faster than in C#.
Conclusion
It seems that the main problem is in insertSuffix(), perhaps my lack of knowledge and understanding of the unordered_map structure. Can anyone shed a light on this? Did I make some rookie mistake in the C++ variant which causes the object construction to take so long?
Aditional Info
I've compiled both the C# and C++ program for maximum speed /O2 (release)
In C#, a System.String includes its Length, so you can get the length in constant time. In C++, a std::string also includes its size, so it is also available in constant time.
However, you aren’t using C++ std::string (which you should be, for a good translation of the algorithm); you’re using a C-style null-terminated char array. That char* literally means “pointer to char”, and just tells you where the first character of the string is. The strlen function looks at each char from the one pointed to forward, until it finds a null character '\0' (not to be confused with a null pointer); this is expensive, and you do it in each iteration of your loop in insertSuffix. That probably accounts for at least a reasonable fraction of your slowdown.
When doing C++, if you find yourself working with raw pointers (any type involving a *), you should always wonder if there’s a simpler way. Sometimes the answer is “no”, but often it’s “yes” (and that’s getting more common as the language evolves). For example, consider your struct node and node* root. Both use node pointers, but in both cases you should have used node directly because there is no need to have that indirection (in the case of node, some amount of indirection is necessary so you don’t have each node containing another node ad infinitum, but that’s provided by the std::unordered_map).
A couple other tips:
In C++ you often don’t want to do any work in the body of a constructor, but instead use initialization lists.
When you don’t want to copy something you pass as a parameter, you should make the parameter a reference; instead of changing insertSuffix to take a std::string as the first parameter, make it take std::string const&; similarly, contains should take a std::string const&. Better yet, since insertSuffix can see the text member, it doesn’t need to take that first parameter at all and can just use from.
C++ supports a foreach-like construct, which you should probably prefer to a standard for loop when iterating over a string’s characters.
If you’re using the newest not-technically-finalized-but-close-enough version of C++, C++17, you should use std::string_view instead of std::string whenever you just want a look at a string, and don’t need to change it or keep a reference to it around. This would be useful for contains, and since you want to make a local copy in the text member, even for the constructor; it would not be useful in the text member itself, because the object being viewed might be temporary. Lifetime can sometimes be tricky in C++, though, and until you get the hang of it you might just want to use std::string to be on the safe side.
Since node isn’t useful outside of the concept of suffixTree, it should probably be inside it, like in the C# version. As a deviation from the C# version, you might want to make the type node and the data members root and text into private instead of public members.
I'm trying to use the Array.ForEach() extension method to loop through for a list of filtered elements from an array and then modify those values, unfortunately that doesn't seem to work I'm guessing because it doesn't actually modify the reference value of each element.
Is there any way to do this besides storing the results of the Array.ForEach() into a seperate array and then cloning that array to the original array? Also I know I could obviously do all of this without cloning if I use a for loop but if I could do it this way it would be cleaner and would be less code.
Here's the snippet:
Array.ForEach(Array.FindAll(starts, e => e < 0), e => e = 0);
ForEach simply isn't intended to do this - just like you wouldn't be able to do this with a foreach loop.
Personally I'd just use a for loop - it's easy to read and clear:
for (int i = 0; i < array.Length; i++)
{
// Alternatively, use Math.Max to pull up any negative values to 0
if (array[i] < 0)
{
array[i] = 0;
}
}
It really is simple - anyone will be able to understand it.
Now you could write your own extension method instead. You could write one to replace all values which satisfy a predicate with a fixed value, or you could write one to replace all values entirely... but I don't think it's really worth it. As an example of the latter:
public static void ReplaceElements<T>(this T[] array,
Func<T, T> replacementFunction)
{
// TODO: Argument validation
for (int i = 0; i < array.Length; i++)
{
array[i] = replacementFunction(array[i]);
}
}
Then call it with:
starts.ReplaceElements(x => Math.Max(x, 0));
I'd personally still use the for loop though.
(You could potentially change the above very slightly to make it take IList<T> and use Count instead. That would still work with arrays, but also List<T> etc too.)
You can do that with ref and delegates. However, I don't think it adds much value.
public delegate void RefAction<T>(ref T value);
public static void ForEachRef<T>(this T[] array, RefAction<T> action)
{
for (int i = 0; i < array.Length; ++i) action(ref array[i]);
}
You can use it as follows:
var myArray = new int[];
myArray.ForEachRef((ref int i) => i = whateverYouLike());
From the standpoint of possibility, there could be an interface IRefEnumerable<T> which iterates some container with assignable elements.
array = array.Select(x => (x < 0) ? 0: x).ToArray();
typedef struct {
int e1;
int e2;
int e3;
int e4;
int e5;
} abc;
void Hello(abc * a, int index)
{
int * post = (&(a->e1) + index);
int i;
for(i = 0; i<5; i++)
{
*(post + i) = i;
}
}
The problem I face here is how they able to access the next element in the struct by
*(post + i)
I'm not sure how all these would be done in C# and moreover, I don't want to use unsafe pointers in C#, but something alternate to it.
Thanks!
You should replace the struct with an array of 5 elements.
If you want to, you can wrap the array in a class with five properties.
edit...
When you say 'Wrap,' it generally means to write properties in a class that set or get the value of either a single variable, an array element, or a member of another class whose instance lives inside your class (the usual usage here = 'wrap an object'). Very useful for separating concerns and joining functionality of multiple objects. Technically, all simple properties just 'wrap' their private member variables.
Sample per comment:
class test
{
int[] e = new int[5];
public void Hello(int index)
{
for (int i = 0; i <= 4; i++) {
// will always happen if index != 0
if (i + index > 4) {
MsgBox("Original code would have overwritten memory. .Net will now blow up.");
}
e[i + index] = i;
}
}
public int e1 {
get { return e[0]; }
set { e[0] = value; }
}
public int e2 {
get { return e[1]; }
set { e[1] = value; }
}
//' ETC etc etc with e3-e5 ...
}
The problem with the C code is that if index is greater than 0 it runs off the end of the abc struct, thus overwriting random memory. This is exactly why C#, a safer language, does not allow these sorts of things. The way I'd implement your code in C# would be:
struct abc
{
public int[] e;
}
void Hello(ref abc a, int index)
{
a.e = new int[5];
for (int i = 0; i < 5; ++i)
a.e[index + i] = i;
}
Note that if index > 0, you'll get an out of bounds exception instead of possibly silent memory overwriting as you would in the C snippet.
The thinking behind the C codes is an ill fit for C#. The C code is based on the assumption that the fields of the struct will be placed sequentially in memory in the order defined the fields are defined in.
The above looks like either homework or a contrived example. Without knowing the real intent it's hard to give a concrete example in C#.
other examples here suggest changing the data structure but if you can't/don't want to do that, you can use reflection combined with an array of objects of the struct type to accomplish the same result as above.
void Hello(abc currentObj){
var fields = typeof(abc).GetFields();
for(var i = 0;i<fields.Length;i++){
fields[i].SetValue(currentObj,i);
}
}
I'm looking for a way to set every value in a multidimensional array to a single value. The problem is that the number of dimensions is unknown at compile-time - it could be one-dimensional, it could be 4-dimensional. Since foreach doesn't let you set values, what is one way that I could achieve this goal? Thanks much.
While this problem appears simple on the surface, it's actually more complicated than it looks. However, by recognizing that visiting every position in a multidimensional (or even jagged) array is a Cartesian product operation on the set of indexes of the array - we can simplify the solution ... and ultimately write a more elegant solution.
We're going to leverage Eric Lippert's LINQ Cartesian Product implementation to do the heavy lifting. You can read more about how that works on his blog if you like.
While this implementation is specific to visiting the cells of a multidimensional array - it should be relatively easy to see how to extend it to visit a jagged array as well.
public static class EnumerableExt
{
// Eric Lippert's Cartesian Product operator...
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct =
new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
}
}
class MDFill
{
public static void Main()
{
// create an arbitrary multidimensional array
Array mdArray = new int[2,3,4,5];
// create a sequences of sequences representing all of the possible
// index positions of each dimension within the MD-array
var dimensionBounds =
Enumerable.Range(0, mdArray.Rank)
.Select(x => Enumerable.Range(mdArray.GetLowerBound(x),
mdArray.GetUpperBound(x) - mdArray.GetLowerBound(x)+1));
// use the cartesian product to visit every permutation of indexes
// in the MD array and set each position to a specific value...
int someValue = 100;
foreach( var indexSet in dimensionBounds.CartesianProduct() )
{
mdArray.SetValue( someValue, indexSet.ToArray() );
}
}
}
It's now trivial to factor this code out into a reusable method that can be used for either jagged or multidimensional arrays ... or any data structure that can be viewed as a rectangular array.
Array.Length will tell you the number of elements the array was declared to store, so an array of arrays (whether rectangular or jagged) can be traversed as follows:
for(var i=0; i<myMDArray.Length; i++)
for(var j=0; j < myMDArray[i].Length; i++)
DoSomethingTo(myMDArray[i][j]);
If the array is rectangular (all child arrays are the same length), you can get the Length of the first array and store in a variable; it will slightly improve performance.
When the number of dimensions is unknown, this can be made recursive:
public void SetValueOn(Array theArray, Object theValue)
{
if(theArray[0] is Array) //we haven't hit bottom yet
for(int a=0;a<theArray.Length;a++)
SetValueOn(theArray[a], theValue);
else if(theValue.GetType().IsAssignableFrom(theArray[0].GetType()))
for(int i=0;i<theArray.Length;i++)
theArray[i] = theValue;
else throw new ArgumentException(
"theValue is not assignable to elements of theArray");
}
I think there is no direct way of doing this, so you'll need to use the Rank property to get the number of dimensions and a SetValue method (that takes an array with index for every dimension as argument).
Some code snippet to get you started (for standard multi-dimensional arrays):
bool IncrementLastIndex(Array ar, int[] indices) {
// Return 'false' if indices[i] == ar.GetLength(i) for all 'i'
// otherwise, find the last index such that it can be incremented,
// increment it and set all larger indices to 0
for(int dim = indices.Length - 1; dim >= 0; dim--) {
if (indices[dim] < ar.GetLength(dim)) {
indices[dim]++;
for(int i = dim + 1; i < indices.Length; i++) indices[i] = 0;
return;
}
}
}
void ClearArray(Array ar, object val) {
var indices = new int[ar.Rank];
do {
// Set the value in the array to specified value
ar.SetValue(val, indices);
} while(IncrementLastIndex(ar, indices));
}
The Array.Clear method will let you clear (set to default value) all elements in a multi-dimensional array (i.e., int[,]). So if you just want to clear the array, you can write Array.Clear(myArray, 0, myArray.Length);
There doesn't appear to be any method that will set all of the elements of an array to an arbitrary value.
Note that if you used that for a jagged array (i.e. int[][]), you'd end up with an array of null references to arrays. That is, if you wrote:
int[][] myArray;
// do some stuff to initialize the array
// now clear the array
Array.Clear(myArray, 0, myArray.Length);
Then myArray[0] would be null.
Are you saying that you want to iterate through each element and (if available) each dimension of an array and set each value along the way?
If that's the case you'd make a recursive function that iterates the dimensions and sets values. Check the Array.Rank property on MSDN and the Array.GetUpperBound function on MSDN.
Lastly, I'm sure generic List<T> has some sort of way of doing this.