Assigning a particular value to array elements



I have an array of 10000 elements. I want to randomly assign energy to these 10000 elements using Gaussian or Exponential distribution, such that each time a particular element is selected its energy should also be shown in the output. Can anyone suggest me how to solve this problem?

Let's say, I have 10 elements in the array {8,4,6,2,9,0,5,1,7,3} and I am assigning energy to these 10 elements randomly. After that I am selecting one of the element in the array, say 7, when I select this number I also want to know the energy that number possesses.

This is the program I wrote to generate 1000 elements.

l = 0;
For[i = 0, i < 10, i++,
 For[j = 0, j < 10, j++,
  For[k = 0, k < 10, k++,
   Xarray[l] = A[i, j, k];

When Xarray[5] is given it will show the coordinate it possesses. In addition to this I want to know the energy when I am giving Xarray[5], Xarray[998], etc.


Posted 2012-07-05T09:56:54.217

Reputation: 299

1Can you give a small example of what you want to see (say, for a ten-element array)? – J. M.'s ennui – 2012-07-05T09:59:07.000

1Daniel, if you will register you account it will be easier for you to edit your questions, post comments, etc. – Mr.Wizard – 2012-07-05T10:26:52.973

2Daniel, I see that you have already registered an account; I merged the temporary ones with this one. You should sign in before posting or editing. – Mr.Wizard – 2012-07-05T10:30:23.343

1You definitely don't need that For loop. Xarray=A @@@ Tuples[Range[0, 9], 3] will do just as well, and it's much, much faster to type and to evaluate. – Verbeia – 2012-07-05T10:43:06.943

Verbeia, Thanks for your wonderful suggestion. I have one doubt, In for loop program if I type Xarray[5], it will show the coordinates. How about this in your suggestion. – Daniel – 2012-07-05T10:49:23.667

@Daniel see my second answer which I have just posted. – Verbeia – 2012-07-05T11:42:04.483



I am adding this as another answer to address some specific issues raised in comments.

First, it is almost always true that "if you are using a For loop in Mathematica, you are doing it wrong". So here is a simpler and faster way to create your array.

Xarray = A @@@ Tuples[Range[0, 9], 3];

You can then write:

energies = 
  RandomVariate[ExponentialDistribution[1.5], {Length@Xarray}];

Now, here is a very simple function that returns an element from Xarray and the matching element from energies. Notice the use of Pick and the pure function using Slot (#) notation.

f = {#, First@Pick[energies, Xarray, #]} &

If you know which element you want to get the element-energy pair for, you would do this:

f@A[0, 0, 4]

(*{A[0, 0, 4], 1.00466}*)

If you just wanted the fifth element, without knowing in advance what it was, you would instead evaluate:


(*{A[0, 0, 4], 1.00466}*)


Posted 2012-07-05T09:56:54.217

Reputation: 33 191

Thank You so much for your kindness in answering my question. – Daniel – 2012-07-05T11:51:25.783

Verbeia, I am new To the programming field. As per your program, energies are assigned to each elements in the array. Now I want to randomly select let say 5 elements from this 1000 element array randomly such that no element should repeat. let { 89,5,79,34,900} be the elements I randomly selected.Now for each element I should get the energies and coordinates automatically. Could you do this. – Daniel – 2012-07-05T12:08:34.223

1yes, but please ask this is a separate question. – Verbeia – 2012-07-05T12:09:51.747

@Daniel Perhaps it's time to read a Mathematica tutorial?

– Ajasja – 2012-07-05T12:11:21.590


Does this simple element-energy pairing solve your problem?

n = 50;
array = Table[i, {i, n}];
energy = RandomVariate[NormalDistribution[0, 1], {n}];

coupled = Thread@{array, energy}; (* this returns a list where each member is an {element, energy} pair *)

Mathematica graphics

István Zachar

Posted 2012-07-05T09:56:54.217

Reputation: 44 135

I'd use Thread[array -> energy] myself. (+1) – Mr.Wizard – 2012-07-05T10:20:01.250


Perhaps something like this is what you are looking for?

Suppose you have an array of objects. I have used the Array function here, but the contents of this array could be anything.

elements = Array[a, {10}]

(*{a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]}*)

Create a separate vector of energies. Since István has already shown the NormalDistribution, I'll use ExponentialDistribution.

energies = RandomVariate[ExponentialDistribution[1.5], {10}]

(*{0.0969302, 0.335765, 0.564123, 1.51769, 0.142579, 0.222407, \
0.842437, 1.35341, 0.239727, 0.0312016}*)

Now consider a function like this, which takes the index of the element and returns both the element and the associated energy. Notice that I have specified that n has to be a positive integer, because indices of lists are always positive integers, and that it must also be less than the total length of the elements list.

getElement[n_Integer?Positive] /; 
  n <= Length[elements] := {elements[[n]], energies[[n]]}


(*{a[4], 1.51769}*)

Because 20 is greater than the current length of elements, getElement[20] is undefined and returns itself unchanged.


(* getElement[20] *)

But if you go back and redefine elements (and energies) to be longer, then re-evaluating getElement[20] will return the 20th element-energy pair.

You could of course include some other checks to make sure that energies is always the same length as elements, but this should be enough to get you started.


Based on your edit, it is possible that this is more appropriate. This function works out the position of the element in a particular vector, and returns that element and the matching element from the energies vector.

getEnergyByElement[elem_, vec_?VectorQ] := 
 With[{n = Position[vec, elem][[1, 1]]}, {vec[[n]], energies[[n]]}]

getEnergyByElement[a[4], elements]
(* {a[4], 1.51769} *)

An even simpler way is

{#, First@Pick[energies, elements, #]} &@a[5]

(*{a[5], 0.142579} *)


Posted 2012-07-05T09:56:54.217

Reputation: 33 191

Thanks Verbeia, for your wonderful suggestion. I have one doubt, In for loop program if I type Xarray[5], it will show the coordinates. How about this in your suggestion.Please help me. – Daniel – 2012-07-05T10:58:29.730

Thank You Verbeia. Your model Suits to my program. – Daniel – 2012-07-05T11:13:48.670


How about this approach which drops the need for extra storage to hold the paired values:

   elements = {8, 4, 6, 2, 9, 0, 5, 1, 7, 3};
   energy = RandomReal[NormalDistribution[0, 1], Length@elements];

Then you can have:


{-0.318708, 1.18351, -0.281984, -0.94776, -1.3151, -1.00745, 1.2463, \ -1.01972, -0.572084, 1.81867}




And with an extra function show you can display both element and energy value:

show = With[{p = First@Position[elements, #]}, {#, energy[[p]]}] &





show /@ {2, 7, 9}

{{2, 1.18351}, {7, 1.2463}, {9, -0.572084}}

If you want to use the array of elements to indirectly access the energies then you can define a function retrieve:

retrieve = With[{p = First@Position[elements, #]}, {#, energy[[p]]}] &

will lead to:

retrieve /@ {2, 7, 9}

{{4, -0.94776}, {5, -1.3151}, {7, 1.2463}}

Then the following code will show all the elements and their associated energies:

retrieve /@ elements

{{8, {-0.318708}}, {4, {1.18351}}, {6, {-0.281984}}, {2, {-0.94776}}, \ {9, {-1.3151}}, {0, {-1.00745}}, {5, {1.2463}}, {1, {-1.01972}}, {7, \ {-0.572084}}, {3, {1.81867}}}


Posted 2012-07-05T09:56:54.217

Reputation: 9 964


I guess I'll show the Rule variation I alluded to in a comment.

keys = {8, 4, 6, 2, 9, 0, 5, 1, 7, 3};

vals = RandomReal[NormalDistribution[0, 1], Length@elements]

rules= Dispatch@Thread[keys -> vals];

{7, 7 /. rules}
{7, 0.698481}
{1, 2, 3} /. rules
{0.144972, -0.757016, -1.02032}
rules[[1, 3]]
6 -> 1.49672

In the last example the [[1, 3]] is required rather than [[3]] because I converted to rules into a Dispatch table for speed; this is needed to access the raw rules.


Posted 2012-07-05T09:56:54.217

Reputation: 259 163