Creating an Array based on range from existing array - arrays

Say I have a std::array
std::array<int,8> foo = {1,2,3,4,5,6,7,8};
Now Is it possible to create a new array from an existing array using a range say from index to 2 till 5. So my new array will have items {3,4,5,6}.
I am aware that I could accomplish this using the manual for loop copy mechanism but I wanted to know if there was a faster way of doing that

If you are expecting some easy syntax (like Python, Matlab or Fortran), no.
As #Sphinx said you can use copy.
std::array<int,8> foo = {1,2,3,4,5,6,7,8};
std::array<int,3> foo2;
std::copy(&foo[2], &foo[5], foo2.begin());
// or std::copy(foo.begin() + 2, foo.begin() + 5, foo2.begin());
but take into account that std::array sizes are compile time constants.
So you may need std::vector<int> if you want make the range size variable.

Related

Using findmin() in data from array composed of mutable struct elements - Julia

Suppose I have the following struct:
mutable struct Car
load
locale
availability
odometer
end
And I have created an array:
fleet = Vector{Car}(undef, num_cars)
for i in 1:num_cars
a, b, c, d = rand(4)
fleet[i] = Car(a, b, c, d)
end
How can I find the smallest (with findmin or similar) or biggest (with?) value from, for example, the odometer of all the cars in my array?
Basically, I want to be able to use conditional statements with struct arrays, e.g.: For every element in my struct array, get the ones that a data satisfy a condition and, from those, get the minimum value of another data.
Thanks!
Finding the minimum value is pretty straightforward, using the minimum function, with a mapping argument:
julia> minimum(x->x.odometer, fleet)
0.08468003971220694
If you also want the index of the minimum, you can use the findmin function. Unfortunately, this does not, for some reason, support a function argument, so you have to create a temporary array, and apply findmin to that:
julia> findmin(getfield.(fleet, :odometer))
(0.08468003971220694, 1)
You can also use getproperty instead of getfield, they do the same thing for your struct, I'm not certain which is preferable. Probably, the most idiomatic solution would be to define accessor functions instead of using the field values directly. For example:
odometer(car::Car) = car.odometer
minimum(odometer, fleet)
findmin(odometer.(fleet))
For maximum values, use maximum and findmax.
Julia is about performance.
You should avoid using untyped structs hence your type definition should be:
mutable struct Car
load::Float64
locale::Float64
availability::Float64
odometer::Float64
end
The code for creating Vector can be shorter:
cars = [Car(rand(4)...) for _ in 1:5]
The most efficient way to find the index of the minimum element is:
julia> Base.isless(c1::Car,c2::Car) = c1.odometer < c2.odometer
julia> findmin(cs)
(Car(0.7623514815463603, 0.7523019237133661, 0.37422766075278413, 0.49830949323733464), 3)

Stacking copies of an array/ a torch tensor efficiently?

I'm a Python/Pytorch user. First, in numpy, let's say I have an array M of size LxL, and i want to have the following
array: A=(M,...,M) of size, say, NxLxL, is there a more elegant/memory efficient way of doing it than :
A=np.array([M]*N) ?
Same question with torch tensor !
Cause, Now, if M is a Variable(torch.tensor), i have to do:
A=torch.autograd.Variable(torch.tensor(np.array([M]*N)))
which is ugly !
Note, that you need to decide whether you would like to allocate new memory for your expanded array or whether you simply require a new view of the existing memory of the original array.
In PyTorch, this distinction gives rise to the two methods expand() and repeat(). The former only creates a new view on the existing tensor where a dimension of size one is expanded to a larger size by setting the stride to 0. Any dimension of size 1 can be expanded to an arbitrary value without allocating new memory. In contrast, the latter copies the original data and allocates new memory.
In PyTorch, you can use expand() and repeat() as follows for your purposes:
import torch
L = 10
N = 20
A = torch.randn(L,L)
A.expand(N, L, L) # specifies new size
A.repeat(N,1,1) # specifies number of copies
In Numpy, there are a multitude of ways to achieve what you did above in a more elegant and efficient manner. For your particular purpose, I would recommend np.tile() over np.repeat(), since np.repeat() is designed to operate on the particular elements of an array, while np.tile() is designed to operate on the entire array. Hence,
import numpy as np
L = 10
N = 20
A = np.random.rand(L,L)
np.tile(A,(N, 1, 1))
If you don't mind creating new memory:
In numpy, you can use np.repeat() or np.tile(). With efficiency in mind, you should choose the one which organises the memory for your purposes, rather than re-arranging after the fact:
np.repeat([1, 2], 2) == [1, 1, 2, 2]
np.tile([1, 2], 2) == [1, 2, 1, 2]
In pytorch, you can use tensor.repeat(). Note: This matches np.tile, not np.repeat.
If you don't want to create new memory:
In numpy, you can use np.broadcast_to(). This creates a readonly view of the memory.
In pytorch, you can use tensor.expand(). This creates an editable view of the memory, so operations like += will have weird effects.
In numpy repeat is faster:
np.repeat(M[None,...], N,0)
I expand the dimensions of the M, and then repeat along that new dimension.

How to re-arrange elements of Array after Deleting

Recently I was reading a Programming book and found this question:
I have an array :
array = [2,3,6,7,8,9,33,22];
Now, Suppose I have deleted the element at 4th position i.e. 8 .
Now I have to rearrange the array as:
Newarray = [2,3,6,7,9,33,22];
How Can I do this. And I have to also minimize the complexity.
Edit I have no choice to make another copy of it.I have to only modify it.
You can "remove" a value from an array by simply copy over the element by the next elements, that's easy to do with memmove:
int array[8] = {2,3,6,7,8,9,33,22};
memmove(&array[4], &array[5], sizeof(int) * 3);
The resulting array will be {2,3,6,7,9,33,22,22}.
And from that you can see the big problem with attempting to "remove" an element from a compile-time array: You can't!
You can overwrite the element, but the size of the array is fixed at time of compilation and can't actually be changed at run-time.
One common solution is to keep track of the actual number of valid elements in the array manually, and make sure you update that size as you add or remove elements. Either that or set unused elements to a value that's not going to be used otherwise (for example if your array can only contain positive numbers, then you could set unused elements to -1 and check for that).
If you don't want to use a library function (why not?) then loop and set e.g.
array[4] = array[5];
array[5] = array[6];
and so on.
Do this, just use these two functions and it will work fine
index=4;//You wanted to delete it from the array.
memcpy(newarray,array,sizeof(array));
memmove(&newarray[index], &newarray[index + 1], sizeof(newarray)-1);
now the newarray contains your exact replica without the character that you wished to remove
You can simply displace each element from the delIdx(deletion index) one step forward.
for(int i=delIdx; i<(arr_size-1);i++)
{
arr[i]= arr[i+1];
}
If required you can either set the last element to a non-attainable value or decrease the size of the array.

Matlab array of struct : Fast assignment

Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.

changing the index of array

so far, i m working on the array with 0th location but m in need to change it from 0 to 1 such that if earlier it started for 0 to n-1 then now it should start form 1 to n. is there any way out to resolve this problem?
C arrays are zero-based and always will be. I strongly suggest sticking with that convention. If you really need to treat the first element as having index 1 instead of 0, you can wrap accesses to that array in a function that does the translation for you.
Why do you need to do this? What problem are you trying to solve?
Array indexing starts at zero in C; you cannot change that.
If you've specific requirements/design scenarios that makes sense to start indexes at one, declare the array to be of length n + 1, and just don't use the zeroth position.
Subtract 1 from the index every time you access the array to achieve "fake 1-based" indexing.
If you want to change the numbering while the program is running, you're asking for something more than just a regular array. If things only ever shift by one position, then allocate (n+1) slots and use a pointer into the array.
enum { array_size = 1000 };
int padded_array[ array_size + 1 ];
int *shiftable_array = padded_array; /* define pointer */
shiftable_array[3] = 5; /* pointer can be used as array */
some_function( shiftable_array );
/* now we want to renumber so element 1 is the new element 0 */
++ shiftable_array; /* accomplished by altering the pointer */
some_function( shiftable_array ); /* function uses new numbering */
If the shift-by-one operation is repeated indefinitely, you might need to implement a circular buffer.
You can't.
Well in fact you can, but you have to tweak a bit. Define an array, and then use a pointer to before the first element. Then you can use indexes 1 to n from this pointer.
int array[12];
int *array_starts_at_one = &array[-1]; // Don't use index 0 on this one
array_starts_at_one[1] = 1;
array_starts_at_one[12] = 12;
But I would advise against doing this.
Some more arguments why arrays are zero based can be found here. Infact its one of the very important and good features of the C programming language. However you can implement a array and start indexing from 1, but that will really take a lot of effort to keep track off.
Say you declare a integer array
int a[10];
for(i=1;i<10;i++)
a[i]=i*i;
You need to access all arrays with the index 1. Ofcourse you need to declare with the size (REQUIRED_SIZE_NORMALLY+1).
You should also note here that you can still access the a[0] element but you have to ignore it from your head and your code to achieve what you want to.
Another problem would be for the person reading your code. He would go nuts trying to figure out why did the numbering start from 1 and was the 0th index used for some hidden purpose which unfortunately he is unaware of.

Resources