【问题标题】:How can I write a function that will create and store variables?如何编写一个创建和存储变量的函数?
【发布时间】:2015-08-02 12:39:15
【问题描述】:

我想要一个函数 function y(x),当我调用 y(5.12) 时,它会创建一个变量 y(5.12)(或者以某种方式记住 y(5.12) 是什么),该函数在函数完成后可以使用跑完了。做这样的事情最简单的方法是什么?

我会创建一个数组并将每个值存储在其对应的单元格中,但我也会有非整数和负值,所以数组不起作用:(

【问题讨论】:

  • 您是否尝试过containers.Map,可能在persistent 变量中?
  • 在过去的几天里,我实际上一直在试图弄清楚 persistent 是如何使用代码的其他部分打开和关闭的,并且最终每次都使用不同的方法(全局)时间......那个功能对我来说仍然很神秘......你能更具体吗?我不完全确定它是如何工作的,让我们在这里应用它。我现在将研究containers.Map,但我从未使用过它
  • 使用persistent而不是global;从长远来看,您的代码会更好地工作。 doco for persistent 涵盖了它。 persistent 表示变量在函数的多次调用中保持其值。清除函数(更改和保存函数时会隐式发生)将重置其持久变量的值;也许这就是混乱的来源。

标签: matlab function memoization


【解决方案1】:

Andrew Janke 是正确的。使用containers.Mapcontainers.Map 就是所谓的associative array。它也被称为符号表、地图或字典。关联数组背后的主干是您通过 key 访问数组,并获得与此键相关的关联值。

最好的例子是英语词典,其中键是您要查找的单词,值是该特定单词的定义。例如(没有任何修饰),假设我们的字典是f,而我使用了rayryeng这个键,一个可能的值可能是:

f('rayryeng') --> he is awesome

现在在 MATLAB 中,可能的键类型列表为:'char', 'double', 'single', 'int32', 'uint32', 'int64', or 'uint64'。可能的值列表是'char', 'logical', 'double', 'single', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', or 'uint64'。给定您的应用程序,听起来您希望键是 double,值是 char

因此,初始化您的 containers.Map 以识别此键/值组合:

f = containers.Map('KeyType','double','ValueType','char')

我们得到这个:

f = 

  Map with properties:

        Count: 0
      KeyType: double
    ValueType: char

此字典中当前没有键/值对,预期键为double,输出值为char。我们可以开始随意添加东西了:

>> f(5.12) = 'hello';
>> f(-1.56) = 'Solarmew';
>> f(pi) = 'YES!';

我添加了 5.12、-1.56 和 pi 的 3 个键,它们具有不同的字符串。现在,如果您想检索给定键的值,只需给出正确的键:

>> x = f(-1.56)

x =

Solarmew

如果您尝试提供一个不存在的密钥,MATLAB 会给您一个错误:

>> y = f(0)

Error using containers.Map/subsref
The specified key is not present in this container.

如果要检查字典中是否存在某个键,请使用isKey 方法:

>> isKey(f, 0)

ans = 

  0

为您提供更多方法。您可以使用keys 方法检索当前字典中的所有键:

>> k = keys(f)

k = 

    [-1.5600]    [3.1416]    [5.1200]

k 是一个元胞数组,其中每个元素都是该字典中的一个键。同样,如果您想要这些值,请使用values 方法:

>> v = values(f);

v = 

    'Solarmew'    'YES!'    'hello'

需要注意的是keysvalues都不保证任何顺序。这意味着您添加键和值的顺序并不一定意味着您在调用keysvalues 时将获得相同的顺序。最后,如果您想从字典中删除键/值对,请使用remove 方法:

>> remove(f, -1.56);
>> k = keys(f)

k = 

    [3.1416]    [5.1200]

>> v = values(f)

v = 

    'YES!'    'hello'

如您所见,与Solarmew 关联的-1.56 的键现在已从字典中删除。


希望这会有所帮助!

【讨论】:

  • 很酷的东西! :] 似乎仍然与函数不兼容(实际分配的来源)w = containers.Map('KeyType','double','ValueType','char');function wOut = w(z) wOut = w0*sqrt(1+(z/zr)^2); w(z) = wOut; end
  • 那是因为你没有正确定义函数。像您一样制作containers.Map,然后将其用作函数的输入。您正在尝试使函数名称和 containers.Map 同名。这样做:function w = f(w, z, w0, zr) w(z) = w0*sqrt(1+(z/zr)^2); end,那么您所要做的就是在工作区中w = f(w, z, w0, zr);w 现在应该使用您放入的任何内容进行更新。
  • 仍然无法正常工作:( ...我在工作区中输入了“w = containers.Map('KeyType','double','ValueType','char');”,然后编辑了我的名为“test”的函数为“function w = test(z) % w(z) = sqrt(z); end”并在工作区中输入“test(0.1)”并返回“尝试访问 (0.1);索引必须是正整数或逻辑整数。”
  • w 也必须是函数的输入。请再次阅读我对您的评论。祝你好运!
  • 因为您正在尝试绘制角色。没有意义
【解决方案2】:

我将使用一个简单的数组和一个persistent 变量来展示我的解决方案。

假设您有一个计算数字平方的函数,并且您想要做一些记忆。

在我的代码中,my_hist 是一个二维向量。第一个维度对应于输入,第二个维度对应于输入的平方(即输出)。

function y = memo_sqr(x)

persistent my_hist;

if(isempty(my_hist))
 my_hist = [0 0];
end

%Find if it is already present

idx = find(my_hist(:,1)==x);

if idx
 disp('Found Entry in Table')
 y = my_hist(idx,2)
 return
end

y = x^2;

my_hist = [my_hist; x y];

pause(2); %Artifical Lag 

end

我引入了一些 2 秒的人为延迟来模拟计算耗时的情况。

现在,如果我第一次运行代码并询问memo_sqr(x),则需要花费一些奇怪的 2 秒来计算(其中包括人为延迟)。但是,如果我再次询问,持久查找表会立即给我答案。

>> tic; memo_sqr(2); toc;
Elapsed time is 2.056881 seconds.
>> tic; memo_sqr(2); toc;
Found Entry in Table

y =

     4

Elapsed time is 0.000545 seconds.

这显然是一个非常简单的示例,但它强调了如何使用persistent 变量。我的 sn-p 的各个步骤可以优化以满足您的需求。

【讨论】:

  • @Solarmew,这只是一个插图。如果您使用元胞数组而不是数组,则可以在其中放置任何数据结构。
  • 我只需要相信你的话+.+ ...我不知道这会如何工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
相关资源
最近更新 更多