从 Hold'd 表达式中提取内容的冒险

发布于 2024-10-13 03:53:28 字数 503 浏览 7 评论 0原文

假设我有一个 param->value 规则列表,其中参数是可能分配有值的符号。例如:

{a, b, c} = {1, 2, 3};
x = Hold[{a->1, b->2, c->3}];

我需要将列表包装在 Hold 中,否则它将计算为 {1->1, 2->2, 3->3}。 (我愿意接受 Hold There 的任何替代方案,如果它能让剩下的事情变得更容易的话。)

现在假设我想将 x 转换成这样:

{"a"->1, "b"->2, "c"->3}

下面的函数将做到这一点:

f[h_] := Block[{a,b,c}, ToString[#[[1]]]->#[[2]]& /@ ReleaseHold@h]

我的问题:你能写一个 f 的版本吗?符号列表 {a,b,c} 不必显式提供?

Suppose I have a list of param->value rules where the params are symbols that might have values assigned to them. For example:

{a, b, c} = {1, 2, 3};
x = Hold[{a->1, b->2, c->3}];

I need the list wrapped in Hold otherwise it would evaluate to {1->1, 2->2, 3->3}. (I'm open to any alternatives to Hold there if it makes the rest of this easier.)

Now suppose I want to convert x into this:

{"a"->1, "b"->2, "c"->3}

The following function will do that:

f[h_] := Block[{a,b,c}, ToString[#[[1]]]->#[[2]]& /@ ReleaseHold@h]

My question: Can you write a version of f where the list of symbols {a,b,c} doesn't have to be provided explicitly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深爱不及久伴 2024-10-20 03:53:28

这是使用 未评估 的方法:

In[1]:= {a, b, c} = {1, 2, 3};

In[2]:= x = Hold[{a -> 1, b -> 2, c -> 3}];

In[3]:= ReleaseHold[
 x /. (symb_ -> e_) :> ToString[Unevaluated[symb]] -> e]

Out[3]= {"a" -> 1, "b" -> 2, "c" -> 3}

Here is a way using Unevaluated:

In[1]:= {a, b, c} = {1, 2, 3};

In[2]:= x = Hold[{a -> 1, b -> 2, c -> 3}];

In[3]:= ReleaseHold[
 x /. (symb_ -> e_) :> ToString[Unevaluated[symb]] -> e]

Out[3]= {"a" -> 1, "b" -> 2, "c" -> 3}
等风来 2024-10-20 03:53:28
{a, b, c} = {1, 2, 3};
x = Hold[{a -> 1, b -> 2, c -> 3}];
f[x_] := Cases[x, HoldPattern[z_ -> y_] :> 
                  StringTake[ToString[(Hold@z)], {6, -2}] -> y, 2];
f[x] // InputForm

Out:

{"a" -> 1, "b" -> 2, "c" -> 3} 

也许不是很优雅,但似乎可行。

{a, b, c} = {1, 2, 3};
x = Hold[{a -> 1, b -> 2, c -> 3}];
f[x_] := Cases[x, HoldPattern[z_ -> y_] :> 
                  StringTake[ToString[(Hold@z)], {6, -2}] -> y, 2];
f[x] // InputForm

Out:

{"a" -> 1, "b" -> 2, "c" -> 3} 

Perhaps not very elegant, but seems to work.

金橙橙 2024-10-20 03:53:28

这是一个有点老的问题,但我认为有一个答案结合了两者的优点 Andrew Moylan 的回答贝利撒留的回答。您确实希望左侧带有 HoldPattern 的规则列表,而不是包含整个事物的 Hold 规则列表,这样您实际上可以使用规则而无需经历任何类型的ReleaseHold过程。

In[1]:= {a, b, c} = {1, 2, 3};

Unevaluated 也有助于构建您想要的列表类型:

In[2]:= x = Thread[HoldPattern /@ Unevaluated[{a, b, c}] -> Range[3]]
Out[2]= {HoldPattern[a] -> 1, HoldPattern[b] -> 2, HoldPattern[c] -> 3}

现在您可以通过规则替换来执行您想要的操作。这有点复杂,但我发现自己一遍又一遍地做这件事。您可能会注意到,此规则列表几乎与 OwnValuesDownValues 列表的形式完全相同,因此能够操作它非常有帮助。诀窍是使用 HoldPatternVerbatim 一致:

In[3]:= f[rules_] :=
         Replace[rules,
          HoldPattern[Verbatim[HoldPattern][s_Symbol] -> rhs_] :>
           With[{string = ToString[Unevaluated[s]]},
            string -> rhs], {1}]

Replace 的级别规范只是为了确保如果 rhs 本身是一条规则或规则列表,不会发生意外情况。

In[4]:= f[x] // InputForm
Out[4]= {"a" -> 1, "b" -> 2, "c" -> 3}

This is a bit of an old question, but I think there's an answer that combines the virtues of both Andrew Moylan's answer and belisarius' answer. You really want to have lists of rules with HoldPattern on the left-hand side, instead of lists of rules that have Hold wrapped around the whole thing, so that you can actually use the rules without having to go through any sort of ReleaseHold process.

In[1]:= {a, b, c} = {1, 2, 3};

Unevaluated can also be helpful in constructing the sort of list you want:

In[2]:= x = Thread[HoldPattern /@ Unevaluated[{a, b, c}] -> Range[3]]
Out[2]= {HoldPattern[a] -> 1, HoldPattern[b] -> 2, HoldPattern[c] -> 3}

Now you can do what you want with rule replacement. It's a bit involved, but it's something I find myself doing over and over and over again. You may notice that this list of rules has almost exactly the form of a list of OwnValues or DownValues, so being able to manipulate it is very helpful. The trick is using HoldPattern and Verbatim in concert:

In[3]:= f[rules_] :=
         Replace[rules,
          HoldPattern[Verbatim[HoldPattern][s_Symbol] -> rhs_] :>
           With[{string = ToString[Unevaluated[s]]},
            string -> rhs], {1}]

The level spec on Replace is just there to make sure nothing unexpected happens if rhs is itself a rule or list of rules.

In[4]:= f[x] // InputForm
Out[4]= {"a" -> 1, "b" -> 2, "c" -> 3}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文