5
    (* P1comb = f[P1]; *)
    P1comb = f[P1] - Count[{  }, P1];
    P2comb = f[P2] - Count[{P1}, P2];
    B1comb = f[B1] - Count[{P1, P2}, B1];
    B2comb = f[B2] - Count[{P1, P2, B1}, B2];
    P3comb = f[P3] - Count[{P1, P2, B1, B2}, P3];
    B3comb = f[B3] - Count[{P1, P2, B1, B2, P3}, B3];

I am writing the above code, which works perfectly fine. Then I noticed a pattern, so I am just wondering if I might be able to write it better (more compactly) and more efficient using something like FoldList or NestList combined with a pure function, like

FoldList/NestList [] & {P1,P2,B1,B2,P3,B3}

Thanks.

Chen Stats Yu
  • 4,986
  • 2
  • 24
  • 50

3 Answers3

5

You might consider using FoldPairList:

Column[
FoldPairList[{f[#2] - count[#, #2], Append[#, #2]} &, {}, {P1, P2, B1,B2, P3, B3}]
]

Mathematica graphics

I have replaced Count with count to display the expression.

It would also commonly be done like this:

elems = {P1, P2, B1, B2, P3, B3};
lists = Most@FoldList[Append, {}, elems];
MapThread[f[#] - count[#2, #] &, {elems, lists}] // Column

Mathematica graphics

C. E.
  • 70,533
  • 6
  • 140
  • 264
  • Thanks for both methods. I'd prefer to use the 1st one as it looks more compact! :) – Chen Stats Yu Jun 18 '18 at 01:21
  • Weirdly, after putting it into my big function, it used double of the execution time. I think it might be caused by Append? But don't worry. That's not really the point here. – Chen Stats Yu Jun 18 '18 at 01:25
2

Here is an example that avoids Append, but does pre-generate the partial sublists from your list:

list = {P1, P2, B1, B2, P3, B3};

f[#1] - Inactive[Count][Reverse[{##2}], #1] & @@@ 
  (Reverse[list[[;; #]]] & /@ Range[Length[list]])

(* Out: 
 {f[P1] - Inactive[Count][{}, P1], 
  f[P2] - Inactive[Count][{P1}, P2], 
  f[B1] - Inactive[Count][{P1, P2}, B1], 
  f[B2] - Inactive[Count][{P1, P2, B1}, B2], 
  f[P3] - Inactive[Count][{P1, P2, B1, B2}, P3], 
  f[B3] - Inactive[Count][{P1, P2, B1, B2, P3}, B3]}
*)

Mathematica graphics

Of course, you should remove the Inactive part in your actual code :-)


See also Any built-in function to generate successive sublists from a list? for alternative ways to generate the initial sublists.

MarcoB
  • 67,153
  • 18
  • 91
  • 189
2
Clear[P1, P2, B1, B2, P3, B3]
Clear[P1comb, P2comb, B1comb, B2comb, P3comb, B3comb]

a = {P1, P2, B1, B2, P3, B3};
b = {P1comb, P2comb, B1comb, B2comb, P3comb, B3comb};

Using lower-case count initially, to be replaced with Count

Array[With[{c = b[[#]]},
   c = f[a[[#]]] - count[Take[a, # - 1], a[[#]]]] &, Length[a]]

Examples

P1comb
-count[{}, P1] + f[P1]
B3comb
-count[{P1, P2, B1, B2, P3}, B3] + f[B3]

Assigning values after symbolic construction.

With[{d = a}, d = {1, 2, 3, 4, 3, 2}];

B2
4
b /. count -> Count
{f[1], f[2], f[3], f[4], -1 + f[3], -1 + f[2]}
Chris Degnen
  • 30,927
  • 2
  • 54
  • 108