Can we turn this for loop into a more elegant Mathematica code?












6












$begingroup$


I am coding stuff manipulating indirection arrays and I have some code like:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];

For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];

Return[dupInvIndir];
];


We agree that this is not a good functional / Mathematica coding style. However, for the moment I have no idea to get an elegant/efficient way to remove the loop (using functions like Map, Scan...). Any suggestion/idea?





to check it works:



ind={3,5,4,2,1,6}
dup={1,2,2,3,3,3}
createDupInvIndir[ind,dup]


Output:



{3,3,1,2,2,3}




More context:





  • indirection: is an indirection array got from SortBy function used with Range[1,n] to sort another array.


  • duplicate: count different successive elements to detect duplicates


The array dupInvIndir that satisfies the relation:



dupInvIndir[[indirection[[i]]]]=duplicate[[i]]


is used to get the positions (taking into account the duplicate) of the sorted data without explictely reordering the data.



Here is a complete working example:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];
For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];
Return[dupInvIndir];
];

createDuplicate[data_List,indirection_?VectorQ]:=
Block[{dup},
dup=Tally[Range[Length[indirection]],(data[[indirection[[#1]]]]==data[[indirection[[#2]]]])&];
dup=Flatten[MapThread[ConstantArray[#1,#2]&,{Range[Length[dup]],Part[dup,All,2]}]];
Return[dup];
];

data={{3,4},{3,5},{1,2},{1,2},{2,3},{3,6},{5,6}}
indirection=SortBy[Range[Length[data]],data[[#]]&] (* {3,4,5,1,2,6,7} *)
duplicate=createDuplicate[data,indirection] (* {1,1,2,3,4,5,6} *)
dupInvIndir=createDupInvIndir[indirection,duplicate] (* {3,4,1,1,2,5,6} <- Final result *)

(* same stuff with *explicit* sort: data components are moved *)
DeleteDuplicates[Sort[data]] (* {{1,2},{2,3},{3,4},{3,5},{3,6},{5,6}} *)


Take the first element of dupInvIndir, 3, it means that the first element of the (implicitely) sorted data array is data[[3]], ( -> {1,2} ).
This can be compared to the explicit DeleteDuplicate[Sort[data]]










share|improve this question











$endgroup$








  • 3




    $begingroup$
    It would be somewhat easier with some context on what you actually try to achieve there...
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    @HenrikSchumacher please holds on, I will add more context
    $endgroup$
    – Picaud Vincent
    yesterday
















6












$begingroup$


I am coding stuff manipulating indirection arrays and I have some code like:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];

For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];

Return[dupInvIndir];
];


We agree that this is not a good functional / Mathematica coding style. However, for the moment I have no idea to get an elegant/efficient way to remove the loop (using functions like Map, Scan...). Any suggestion/idea?





to check it works:



ind={3,5,4,2,1,6}
dup={1,2,2,3,3,3}
createDupInvIndir[ind,dup]


Output:



{3,3,1,2,2,3}




More context:





  • indirection: is an indirection array got from SortBy function used with Range[1,n] to sort another array.


  • duplicate: count different successive elements to detect duplicates


The array dupInvIndir that satisfies the relation:



dupInvIndir[[indirection[[i]]]]=duplicate[[i]]


is used to get the positions (taking into account the duplicate) of the sorted data without explictely reordering the data.



Here is a complete working example:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];
For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];
Return[dupInvIndir];
];

createDuplicate[data_List,indirection_?VectorQ]:=
Block[{dup},
dup=Tally[Range[Length[indirection]],(data[[indirection[[#1]]]]==data[[indirection[[#2]]]])&];
dup=Flatten[MapThread[ConstantArray[#1,#2]&,{Range[Length[dup]],Part[dup,All,2]}]];
Return[dup];
];

data={{3,4},{3,5},{1,2},{1,2},{2,3},{3,6},{5,6}}
indirection=SortBy[Range[Length[data]],data[[#]]&] (* {3,4,5,1,2,6,7} *)
duplicate=createDuplicate[data,indirection] (* {1,1,2,3,4,5,6} *)
dupInvIndir=createDupInvIndir[indirection,duplicate] (* {3,4,1,1,2,5,6} <- Final result *)

(* same stuff with *explicit* sort: data components are moved *)
DeleteDuplicates[Sort[data]] (* {{1,2},{2,3},{3,4},{3,5},{3,6},{5,6}} *)


Take the first element of dupInvIndir, 3, it means that the first element of the (implicitely) sorted data array is data[[3]], ( -> {1,2} ).
This can be compared to the explicit DeleteDuplicate[Sort[data]]










share|improve this question











$endgroup$








  • 3




    $begingroup$
    It would be somewhat easier with some context on what you actually try to achieve there...
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    @HenrikSchumacher please holds on, I will add more context
    $endgroup$
    – Picaud Vincent
    yesterday














6












6








6


1



$begingroup$


I am coding stuff manipulating indirection arrays and I have some code like:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];

For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];

Return[dupInvIndir];
];


We agree that this is not a good functional / Mathematica coding style. However, for the moment I have no idea to get an elegant/efficient way to remove the loop (using functions like Map, Scan...). Any suggestion/idea?





to check it works:



ind={3,5,4,2,1,6}
dup={1,2,2,3,3,3}
createDupInvIndir[ind,dup]


Output:



{3,3,1,2,2,3}




More context:





  • indirection: is an indirection array got from SortBy function used with Range[1,n] to sort another array.


  • duplicate: count different successive elements to detect duplicates


The array dupInvIndir that satisfies the relation:



dupInvIndir[[indirection[[i]]]]=duplicate[[i]]


is used to get the positions (taking into account the duplicate) of the sorted data without explictely reordering the data.



Here is a complete working example:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];
For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];
Return[dupInvIndir];
];

createDuplicate[data_List,indirection_?VectorQ]:=
Block[{dup},
dup=Tally[Range[Length[indirection]],(data[[indirection[[#1]]]]==data[[indirection[[#2]]]])&];
dup=Flatten[MapThread[ConstantArray[#1,#2]&,{Range[Length[dup]],Part[dup,All,2]}]];
Return[dup];
];

data={{3,4},{3,5},{1,2},{1,2},{2,3},{3,6},{5,6}}
indirection=SortBy[Range[Length[data]],data[[#]]&] (* {3,4,5,1,2,6,7} *)
duplicate=createDuplicate[data,indirection] (* {1,1,2,3,4,5,6} *)
dupInvIndir=createDupInvIndir[indirection,duplicate] (* {3,4,1,1,2,5,6} <- Final result *)

(* same stuff with *explicit* sort: data components are moved *)
DeleteDuplicates[Sort[data]] (* {{1,2},{2,3},{3,4},{3,5},{3,6},{5,6}} *)


Take the first element of dupInvIndir, 3, it means that the first element of the (implicitely) sorted data array is data[[3]], ( -> {1,2} ).
This can be compared to the explicit DeleteDuplicate[Sort[data]]










share|improve this question











$endgroup$




I am coding stuff manipulating indirection arrays and I have some code like:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];

For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];

Return[dupInvIndir];
];


We agree that this is not a good functional / Mathematica coding style. However, for the moment I have no idea to get an elegant/efficient way to remove the loop (using functions like Map, Scan...). Any suggestion/idea?





to check it works:



ind={3,5,4,2,1,6}
dup={1,2,2,3,3,3}
createDupInvIndir[ind,dup]


Output:



{3,3,1,2,2,3}




More context:





  • indirection: is an indirection array got from SortBy function used with Range[1,n] to sort another array.


  • duplicate: count different successive elements to detect duplicates


The array dupInvIndir that satisfies the relation:



dupInvIndir[[indirection[[i]]]]=duplicate[[i]]


is used to get the positions (taking into account the duplicate) of the sorted data without explictely reordering the data.



Here is a complete working example:



createDupInvIndir[indirection_?VectorQ,duplicate_?VectorQ]:=
Block[{n,dupInvIndir},
n=Length[indirection];
Assert[n==Length[duplicate]];
dupInvIndir=ConstantArray[0,n];
For[i=1,i<=n,i++,
dupInvIndir[[indirection[[i]]]]=duplicate[[i]];
];
Return[dupInvIndir];
];

createDuplicate[data_List,indirection_?VectorQ]:=
Block[{dup},
dup=Tally[Range[Length[indirection]],(data[[indirection[[#1]]]]==data[[indirection[[#2]]]])&];
dup=Flatten[MapThread[ConstantArray[#1,#2]&,{Range[Length[dup]],Part[dup,All,2]}]];
Return[dup];
];

data={{3,4},{3,5},{1,2},{1,2},{2,3},{3,6},{5,6}}
indirection=SortBy[Range[Length[data]],data[[#]]&] (* {3,4,5,1,2,6,7} *)
duplicate=createDuplicate[data,indirection] (* {1,1,2,3,4,5,6} *)
dupInvIndir=createDupInvIndir[indirection,duplicate] (* {3,4,1,1,2,5,6} <- Final result *)

(* same stuff with *explicit* sort: data components are moved *)
DeleteDuplicates[Sort[data]] (* {{1,2},{2,3},{3,4},{3,5},{3,6},{5,6}} *)


Take the first element of dupInvIndir, 3, it means that the first element of the (implicitely) sorted data array is data[[3]], ( -> {1,2} ).
This can be compared to the explicit DeleteDuplicate[Sort[data]]







performance-tuning vector permutation coding-style






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday







Picaud Vincent

















asked yesterday









Picaud VincentPicaud Vincent

1,065517




1,065517








  • 3




    $begingroup$
    It would be somewhat easier with some context on what you actually try to achieve there...
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    @HenrikSchumacher please holds on, I will add more context
    $endgroup$
    – Picaud Vincent
    yesterday














  • 3




    $begingroup$
    It would be somewhat easier with some context on what you actually try to achieve there...
    $endgroup$
    – Henrik Schumacher
    yesterday










  • $begingroup$
    @HenrikSchumacher please holds on, I will add more context
    $endgroup$
    – Picaud Vincent
    yesterday








3




3




$begingroup$
It would be somewhat easier with some context on what you actually try to achieve there...
$endgroup$
– Henrik Schumacher
yesterday




$begingroup$
It would be somewhat easier with some context on what you actually try to achieve there...
$endgroup$
– Henrik Schumacher
yesterday












$begingroup$
@HenrikSchumacher please holds on, I will add more context
$endgroup$
– Picaud Vincent
yesterday




$begingroup$
@HenrikSchumacher please holds on, I will add more context
$endgroup$
– Picaud Vincent
yesterday










1 Answer
1






active

oldest

votes


















9












$begingroup$

Apparently, you try to apply a permutation given by list indirection to a vector duplicate.



Here are several ways to do it, each along with its timing:



n = 1000000;
indirection = RandomSample[Range[n], n];
duplicate = RandomInteger[{-n, n}, n];


First@RepeatedTiming[
result0 = createDupInvIndir[indirection, duplicate];
]

First@RepeatedTiming[
result1 = ConstantArray[0, Length[duplicate]];
result1[[indirection]] = duplicate;
]

First@RepeatedTiming[
result2 =
Normal@SparseArray[Partition[indirection, 1] -> duplicate,Length[duplicate]];
]

First@RepeatedTiming[
result3 = duplicate[[InversePermutation@indirection]];
]

result0 == result1 == result2 == result3



1.799



0.012



0.016



0.015



True




This is another one of the many examples that highlights why For should not be used (in uncompiled code).






share|improve this answer











$endgroup$













  • $begingroup$
    Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
    $endgroup$
    – Picaud Vincent
    yesterday










  • $begingroup$
    The benchmark you just added confirms my feeling about perfs. Thanks a lot
    $endgroup$
    – Picaud Vincent
    yesterday






  • 1




    $begingroup$
    You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 1




    $begingroup$
    For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
    $endgroup$
    – Daniel Lichtblau
    yesterday










  • $begingroup$
    It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
    $endgroup$
    – Lukas Lang
    yesterday











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
});
});
}, "mathjax-editing");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "387"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f190569%2fcan-we-turn-this-for-loop-into-a-more-elegant-mathematica-code%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









9












$begingroup$

Apparently, you try to apply a permutation given by list indirection to a vector duplicate.



Here are several ways to do it, each along with its timing:



n = 1000000;
indirection = RandomSample[Range[n], n];
duplicate = RandomInteger[{-n, n}, n];


First@RepeatedTiming[
result0 = createDupInvIndir[indirection, duplicate];
]

First@RepeatedTiming[
result1 = ConstantArray[0, Length[duplicate]];
result1[[indirection]] = duplicate;
]

First@RepeatedTiming[
result2 =
Normal@SparseArray[Partition[indirection, 1] -> duplicate,Length[duplicate]];
]

First@RepeatedTiming[
result3 = duplicate[[InversePermutation@indirection]];
]

result0 == result1 == result2 == result3



1.799



0.012



0.016



0.015



True




This is another one of the many examples that highlights why For should not be used (in uncompiled code).






share|improve this answer











$endgroup$













  • $begingroup$
    Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
    $endgroup$
    – Picaud Vincent
    yesterday










  • $begingroup$
    The benchmark you just added confirms my feeling about perfs. Thanks a lot
    $endgroup$
    – Picaud Vincent
    yesterday






  • 1




    $begingroup$
    You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 1




    $begingroup$
    For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
    $endgroup$
    – Daniel Lichtblau
    yesterday










  • $begingroup$
    It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
    $endgroup$
    – Lukas Lang
    yesterday
















9












$begingroup$

Apparently, you try to apply a permutation given by list indirection to a vector duplicate.



Here are several ways to do it, each along with its timing:



n = 1000000;
indirection = RandomSample[Range[n], n];
duplicate = RandomInteger[{-n, n}, n];


First@RepeatedTiming[
result0 = createDupInvIndir[indirection, duplicate];
]

First@RepeatedTiming[
result1 = ConstantArray[0, Length[duplicate]];
result1[[indirection]] = duplicate;
]

First@RepeatedTiming[
result2 =
Normal@SparseArray[Partition[indirection, 1] -> duplicate,Length[duplicate]];
]

First@RepeatedTiming[
result3 = duplicate[[InversePermutation@indirection]];
]

result0 == result1 == result2 == result3



1.799



0.012



0.016



0.015



True




This is another one of the many examples that highlights why For should not be used (in uncompiled code).






share|improve this answer











$endgroup$













  • $begingroup$
    Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
    $endgroup$
    – Picaud Vincent
    yesterday










  • $begingroup$
    The benchmark you just added confirms my feeling about perfs. Thanks a lot
    $endgroup$
    – Picaud Vincent
    yesterday






  • 1




    $begingroup$
    You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 1




    $begingroup$
    For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
    $endgroup$
    – Daniel Lichtblau
    yesterday










  • $begingroup$
    It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
    $endgroup$
    – Lukas Lang
    yesterday














9












9








9





$begingroup$

Apparently, you try to apply a permutation given by list indirection to a vector duplicate.



Here are several ways to do it, each along with its timing:



n = 1000000;
indirection = RandomSample[Range[n], n];
duplicate = RandomInteger[{-n, n}, n];


First@RepeatedTiming[
result0 = createDupInvIndir[indirection, duplicate];
]

First@RepeatedTiming[
result1 = ConstantArray[0, Length[duplicate]];
result1[[indirection]] = duplicate;
]

First@RepeatedTiming[
result2 =
Normal@SparseArray[Partition[indirection, 1] -> duplicate,Length[duplicate]];
]

First@RepeatedTiming[
result3 = duplicate[[InversePermutation@indirection]];
]

result0 == result1 == result2 == result3



1.799



0.012



0.016



0.015



True




This is another one of the many examples that highlights why For should not be used (in uncompiled code).






share|improve this answer











$endgroup$



Apparently, you try to apply a permutation given by list indirection to a vector duplicate.



Here are several ways to do it, each along with its timing:



n = 1000000;
indirection = RandomSample[Range[n], n];
duplicate = RandomInteger[{-n, n}, n];


First@RepeatedTiming[
result0 = createDupInvIndir[indirection, duplicate];
]

First@RepeatedTiming[
result1 = ConstantArray[0, Length[duplicate]];
result1[[indirection]] = duplicate;
]

First@RepeatedTiming[
result2 =
Normal@SparseArray[Partition[indirection, 1] -> duplicate,Length[duplicate]];
]

First@RepeatedTiming[
result3 = duplicate[[InversePermutation@indirection]];
]

result0 == result1 == result2 == result3



1.799



0.012



0.016



0.015



True




This is another one of the many examples that highlights why For should not be used (in uncompiled code).







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









Henrik SchumacherHenrik Schumacher

51.9k469146




51.9k469146












  • $begingroup$
    Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
    $endgroup$
    – Picaud Vincent
    yesterday










  • $begingroup$
    The benchmark you just added confirms my feeling about perfs. Thanks a lot
    $endgroup$
    – Picaud Vincent
    yesterday






  • 1




    $begingroup$
    You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 1




    $begingroup$
    For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
    $endgroup$
    – Daniel Lichtblau
    yesterday










  • $begingroup$
    It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
    $endgroup$
    – Lukas Lang
    yesterday


















  • $begingroup$
    Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
    $endgroup$
    – Picaud Vincent
    yesterday










  • $begingroup$
    The benchmark you just added confirms my feeling about perfs. Thanks a lot
    $endgroup$
    – Picaud Vincent
    yesterday






  • 1




    $begingroup$
    You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
    $endgroup$
    – Henrik Schumacher
    yesterday






  • 1




    $begingroup$
    For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
    $endgroup$
    – Daniel Lichtblau
    yesterday










  • $begingroup$
    It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
    $endgroup$
    – Lukas Lang
    yesterday
















$begingroup$
Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
$endgroup$
– Picaud Vincent
yesterday




$begingroup$
Thanks for this quick answer, I already had the Normal @ SparseArray solution in mind but I eliminated it because I had the feeling it was not optimal concerning efficiency (a lot of manupilation, rules, array etc..). I did not know about the ToPackedArray package, thanks! (and yes indirection is a permutation of [1..Length[duplicate]])
$endgroup$
– Picaud Vincent
yesterday












$begingroup$
The benchmark you just added confirms my feeling about perfs. Thanks a lot
$endgroup$
– Picaud Vincent
yesterday




$begingroup$
The benchmark you just added confirms my feeling about perfs. Thanks a lot
$endgroup$
– Picaud Vincent
yesterday




1




1




$begingroup$
You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
$endgroup$
– Henrik Schumacher
yesterday




$begingroup$
You're welcome. Developer`ToPackedArray is useful if you handle unpacked arrays that could be packed (with pure machine integers or machine precision numbers (real or complex)). Of course, it is always better never to produce any unpacked arrays. Developer`PackedArrayQ lets you check whether an array is packed or not. I removed the use of Developer`ToPackedArray in my answer since RandomSample and RandomInteger are guaranteed to produce packed arrays (if the occurring integers are not too large).
$endgroup$
– Henrik Schumacher
yesterday




1




1




$begingroup$
For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
$endgroup$
– Daniel Lichtblau
yesterday




$begingroup$
For and the like can be quite useful. They are no substitute when alternatives exist that are vectorized though.
$endgroup$
– Daniel Lichtblau
yesterday












$begingroup$
It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
$endgroup$
– Lukas Lang
yesterday




$begingroup$
It might be worth nothing that replacing the For loop with a Do loop directly gives you a 25% speedup, without doing anything fancy. Also, it seems you've accidentally deleted the definition of ToPack from your answer...
$endgroup$
– Lukas Lang
yesterday


















draft saved

draft discarded




















































Thanks for contributing an answer to Mathematica Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f190569%2fcan-we-turn-this-for-loop-into-a-more-elegant-mathematica-code%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

If I really need a card on my start hand, how many mulligans make sense? [duplicate]

Alcedinidae

Can an atomic nucleus contain both particles and antiparticles? [duplicate]