5
$\begingroup$

For the description, I have a simplified problem like the following:

MapAt[f[1, #1], {a, b, c, d}, #2] & @@@ {{1, 2}, {3, 4}}

will give

{{a, f[1, 1][b], c, d}, {a, b, c, f[1, 3][d]}}

But actually {a, f[1, 1][b], c, f[1, 3][d]} is what I expected. What happened? How to adjust the code?


Update:

My real case is

bigList = Range @ 10;
veryBigList = {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4, 10}};
Function[{binLevel, place}, 
         MapAt[BitSet[#, binLevel] &, bigList, place]] @@@ veryBigList

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 6, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 13, 10}, {1,
2, 3, 4, 5, 6, 7, 8, 9, 26}}

In my case, the list size is very huge. If I use Fold, it will act on a very big result list every calculation, for the RAM so I want to avoid using Fold.

$\endgroup$
  • 3
    $\begingroup$ Would it help you if I rewrote your code as {MapAt[f[1, 1], {a, b, c, d}, 2], MapAt[f[1, 3], {a, b, c, d}, 4]}? $\endgroup$ – J. M. will be back soon Oct 12 '16 at 13:48
  • $\begingroup$ @J.M. Confusing still,as my degree of familiarity about this two functions,it won't give that result. $\endgroup$ – yode Oct 12 '16 at 13:52
  • $\begingroup$ @Kuba 2 and 4 represent place.In you case,it should be {a,f[1,2][f[1,1][b]],c,d} $\endgroup$ – yode Oct 12 '16 at 13:56
  • $\begingroup$ @march When the third parameter is number,you can omit the {} $\endgroup$ – yode Oct 12 '16 at 15:46
  • 2
    $\begingroup$ I mean, using @@@, you are applying the MapAt[ ... ]& function to each element of the list, and so you generate a two element list, as you've found. $\endgroup$ – march Oct 12 '16 at 15:47
4
$\begingroup$
Fold[
 Function[{data, spec}, MapAt[f[1, #1], data, #2] & @@ spec],
 {a, b, c, d},
 {{1, 2}, {3, 4}}
 ]
{a, f[1, 1][b], c, f[1, 3][d]}
$\endgroup$
  • $\begingroup$ Thanks for your method of Fold,but in my real case,I want to avoid it.Can we? $\endgroup$ – yode Oct 12 '16 at 14:51
  • $\begingroup$ If use the Fold,In my case I should change it into Fold[Function[{data,spec},Function[{binLevel,place},MapAt[BitSet[#,binLevel]&,data,place]]@@spec],bigList,veryBigList]? It's very very slow as I try. $\endgroup$ – yode Oct 12 '16 at 16:03
  • $\begingroup$ @yode what is the order of magnitude of length of bigList and a veryBigList? $\endgroup$ – Kuba Oct 13 '16 at 6:22
  • $\begingroup$ bigList is $10^6$.veryBigList is $10^7$ or more $\endgroup$ – yode Oct 13 '16 at 9:49
2
$\begingroup$

This may be the fastest way in my analysis so far and may compete with Fold or perhaps perform better

Module[{m = Range@10},
SetAttributes[func, HoldFirst];
func[x_, {}] := x; 
func[x_, y_] := (x[[y[[1, 2]] ]] = BitSet[x[[y[[1, 2]]]], y[[1, 1]]];
func[x, Rest@y]);

func[m, {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4, 10}}] // AbsoluteTiming
]

(* {0.0000401216, {1, 2, 3, 6, 5, 6, 7, 8, 13, 26}} *)

other attempts

Module[{list = Range@10, i = 0, pos, ind,
indices = {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4, 10}}},
Nest[(pos = indices[[++i, 2]];
ind = indices[[i, 1]];
ReplacePart[#, pos -> BitSet[#[[pos]], ind]]) &, list, 
Length@indices]]// AbsoluteTiming

(* {0.0000979715, {1, 2, 3, 6, 5, 6, 7, 8, 13, 26}} *)

this can be made faster using:

Module[{list = Range@10, i = 0, pos, ind,
indices = {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4, 10}}},
Nest[(pos = indices[[++i, 2]];
ind = indices[[i, 1]];
list[[pos]] = BitSet[list[[pos]], ind];
list) &, list, Length@indices]] // AbsoluteTiming

(* {0.0000639147, {1, 2, 3, 6, 5, 6, 7, 8, 13, 26}} *)

with Do we can get slightly better:

Module[{list = Range@10, pos, ind, 
indices = {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4, 10}}},
Do[(pos = i[[2]];
 ind = i[[1]];
 list[[pos]] = BitSet[list[[pos]], ind]);,
{i, indices}];list] // AbsoluteTiming

(* {0.0000513184, {1, 2, 3, 6, 5, 6, 7, 8, 13, 26}} *)

However, the method suggested by Kuba is still the fastest

Fold[Function[{data, spec}, 
MapAt[BitSet[#, spec[[1]]] &, data, #2] & @@ spec], 
Range@10, {{1, 3}, {1, 4}, {2, 7}, {2, 9}, {4,10}}] // AbsoluteTiming
(* {0.0000438539, {1, 2, 3, 6, 5, 6, 7, 8, 13, 26}} *)
$\endgroup$
2
$\begingroup$
ClearAll[f1]
f1[func_, lst_] :=  Module[{funcs = func[1, #] & @@@ #, pos = #2 & @@@ #}, 
    ReplacePart[lst, Thread[pos -> MapThread[# @ #2 &, {funcs, lst[[pos]]}]]]] &;

f1[f, {a, b, c, d}]@{{1, 2}, {3, 4}}

{a, f[1, 1][b], c, f[1, 3][d]}

or

ClearAll[f2]
f2[func_, lst_] := Module[{funcs = func[1, #] & @@@ #, pos = #2 & @@@ #, l2 = lst}, 
    l2[[pos]] = MapThread[#@#2 &, {funcs, lst[[pos]]}]; l2] &;

f2[f, {a, b, c, d}]@{{1, 2}, {3, 4}}

{a, f[1, 1][b], c, f[1, 3][d]}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.