让我们看看我是否理解你的问题。
我将一步一步地在 Mathematica 中发布代码,以及注释输出以便轻松跟进。
这个答案提供了确定性和有序的输出(即非洗牌)。如果您真的需要随机排列,您可以使用相同的算法预先生成一个完整的过滤序列,将其打乱,并一个一个地使用这些值。
该程序
首先我们定义两个常量:
n = 10; (* nbr of ids *)
m = 3; (* max weight - 1 *)
我保持数字很小,以便我们可以逐步检查输出。
现在我们定义一个随机的 { id, weight} 表来使用。我们使用素数作为 id:
weights = Table[{Prime@k, RandomInteger[m] + 1}, {k, n}]
输出:
{{2, 3}, {3, 2}, {5, 3}, {7, 1}, {11, 1},
{13, 3}, {17, 1}, {19,4}, {23, 1}, {29, 2}}
接下来我们累积权重值
accumulator = Accumulate[Table[k[[2]], {k, weights}]]
输出:
{3, 5, 8, 9, 10, 13, 14, 18, 19, 21}
我们合并两个表以将累加器放入 id 表中:
weightsAcc = MapThread[Append, {weights, accumulator}]
输出:
{{2, 3, 3}, {3, 2, 5}, {5, 3, 8}, {7, 1, 9}, {11, 1, 10},
{13, 3, 13}, {17, 1, 14}, {19, 4, 18}, {23, 1, 19}, {29, 2, 21}}
现在我们使用您的默认值(true 或 false)初始化过滤器。我用了真:
filter = Table[{k[[1]], True}, {k, weights}]
输出:
{{2, True}, {3, True}, {5, True}, {7, True}, {11, True}, {13, True},
{17, True}, {19, True}, {23, True}, {29, True}}
诀窍是使过滤器与 ids 向量保持同步,因此我们定义了一个函数来以这种方式更新过滤器:
updateFilter[filter_, newValuePair_] :=Return@
ReplaceAll[filter, {newValuePair[[1]], x_} -> newValuePair];
并用它来改变两个值:
filter = updateFilter[filter, {2, False}];
filter = updateFilter[filter, {5, False}];
Print@filter
输出:
{{2,False},{3,True},{5,False},{7,True},{11,True},{13,True},
{17,True},{19,True},{23,True},{29,True}}
现在我们定义我们的查询。我们将使用两个全局变量(agrhhhh!)和两个函数来使事物同步:
i = 1; j = 0; (* GLOBAL state variables *)
Adjustij[w_] := ( (* parm w is weightsAcc *)
j++; (* increment accumulator comparator*)
If[j == w[[i, 3]], i++]; (* if current id exhausted, get next*)
If[i == Length@w, i = 1; j = 0]; (* wraparound table when exhausted*)
);
query[w_, filter_] := (* parm w is weightsAcc *)
(
Adjustij[w];
While[Not@filter[[i, 2]], Adjustij[w]]; (* get non filtered ids only *)
Return[w[[i, 1]]];
)
当然,可以通过过滤器 False 跳过 id 来加速 while 循环,但我认为这样的意图更清楚。
现在我们执行 30 次查询:
Table[query[weightsAcc, filter], {30}]
并得到:
{3, 3, 7, 11, 13, 13, 13, 17, 19, 19, 19, 19, 23, 3, 3, 7, 11, 13, \
13, 13, 17, 19, 19, 19, 19, 23, 3, 3, 7, 11}
这是我们的列表(循环地),具有适当的权重,但过滤器为 FALSE 的值除外。
!
编辑:服务器和客户端代码拆分以回答评论
它可以处理具有不同过滤器的并发查询
过滤器状态存储在客户端。
服务器实现的功能和代码:
Clear["Global`*"];
(*Server Implemented Functions follows*)
AdjustFilterState[fs_] := Module[{i, j}, ( (*fs = filterstate, i,j localvars*)
i = fs[[1]]; (*local vars*) (*w = weights with accs*)
j = fs[[2]];
j++; (* increment accumulator comparator*)
If[j == weightsAcc[[i, 3]], i++]; (* if current id exhausted, get next*)
If[i == Length@weightsAcc, i = 1; j = 0];(* wraparound table when exhausted*)
Return[{i, j}];);
];
query[filter_, fs_] := Module[{fsTemp}, (*fs = filterstate*)
(
fsTemp = AdjustFilterState[fs]; (* local var *)
While[Not@filter[[fsTemp[[1]], 2]], (* get non filtered ids only *)
fsTemp = AdjustFilterState[fsTemp]
];
Return[{weightsAcc[[fsTemp[[1]], 1]], fsTemp}]; (*return[value,{filterState}]*)
)
];
initFilter[] := masterFilter; (*Init filters to your defult vallue*)
(*The trick is to get the filter coordinated with the list value*)
updateFilter[f_, newValuePair_] :=
Return@ReplaceAll[f, {newValuePair[[1]], x_} -> newValuePair];
(*Server Code - Just initialize the whole thing
The SERVER stores ONLY the weights vectors and a master filter initialized*)
n = 10; (* nbr of ids *) (*init vars*)
m = 3; (*max weight - 1 *)
weights = Table[{Prime@k, RandomInteger[m] + 1}, {k, n}]; (*random weights to test*)
accumulator = Accumulate[Table[k[[2]], {k, weights}]];
weightsAcc = MapThread[Append, {weights, accumulator}]; (*add acummulator to list*)
masterFilter= Table[{k[[1]],True}, {k,weights}]; (* only ONE virgin filter in server*)
客户端代码:
(* Client Code
The CLIENT stores only the filter and the filterState*)
(* Set up filter and filterstate *)
filter = initFilter[];
filter = updateFilter[filter, {2, False}]; (*specify particular values*)
filter = updateFilter[filter, {5, False}];
filterState = {1,0}; (* these replace the previous GLOBAL state variables *)
ValuesList = {}; (*for storing results *)
Do[
q1 = query[filter, filterState]; (* do the query *)
AppendTo[ValuesList, q1[[1]]]; (* first element of return is the value *)
filterState = q1[[2]]; (* second element is updated filter state *)
, {30} (*do 30 times*)
];
Print@ValuesList (* print results vector *)