如何将一个数字字符串转换为一个数字范围?

30视图(30天)
我使用一个GUI允许用户选择自定义组数字。总是存储为字符串的输入;然而,我需要将字符串转换为一系列的数字。
例如,如果用户输入…
(1:3 5七章)
然后我想要存储的价值……
(1、2、3、5、7,8,9)
有办法不使用eval () ?
eval (“(1:3 5 7:9)”)
我知道使用eval()是不允许的,但我不能想到一个更高效的方法。我唯一的其他想法一直使用正则表达式()这需要更多的时间,因为所有的条件方面的搜索。
注:我知道可以在命令窗口中,但是我试图只使用GUI功能或其他类似的函数创建一个弹出窗口,如:
inputdlg ()

接受的答案

Stephen23
Stephen23 2017年9月20日
编辑:Stephen23 2020年3月8日
函数= str2vec (str)
vec = sscanf (str(2:结束),“% f % c”);
= [];
idb = 1;
ide = 1;
idb < =元素个数(vec)
vec (idb ide = idb + 2 * (+ 1) = = 58);% 58 = =‘:’
= (vec (idb):, vec (ide)];
idb = ide + 2;
结束
结束
它允许任何小数和整数数字(包括可选的+ / -标志和e表示法),通过一个冒号或一个逗号分开。为每个字符数领先的空间将被忽略,而尾部空格导致一个不正确的输出。它可以适应允许的可选的步骤 结肠 命令。
使用你的示例数据输出:
28 29 30 31 32 33 5 7 8 9 20%这个函数
28 29 30 31 32 33 5 7 8 9 20% eval
3评论
撒母耳鼠尾草属的植物
这个函数在电脑上跑得快比eval ()。我一直在测试不同的输入和它工作得很好。在更大的范围可以慢下来,但是我将加入一些警告用户如果他们试一试。
不过我很感兴趣你的函数。我真的没有机会查看它。(我从来没有使用vec()函数)。虽然,我很感兴趣找出为什么它这么快就工作。

登录置评。

更多的答案(3)

强迫症
强迫症 2017年9月19日
编辑:强迫症 2017年9月19日
在用户输入无序的范围情况下,重复的数字,或负数,这个解决方案也快~ 3倍。但是你可能需要更多的错误处理功能,无法预测的所有类型的输入。
Str =“1:3,9:4,七章”;%用户输入一个怪异的范围。不需要括号
StrParts = cellfun (@ (x)正则表达式(x,“:”,“分裂”),正则表达式(Str,' \ - * \ d +: \ - * \ d + | \ - * \ d +”,“匹配”),“UniformOutput”、假);
NumParts = cellfun (@ (x) str2double (x (1)): str2double (x(结束),StrParts,“UniformOutput”、假);
范围=独特(猫(NumParts {:}));
范围=
9 8 7 6 5 4 1 2 3 7 8 9
3评论
强迫症
强迫症 2017年9月20日
编辑:强迫症 2017年9月20日
是的,我找不到比eval。我有一个更快的解决方案,仅低于2.6倍 eval 基于10000次迭代。见下文。否则,沃尔特的解决方案使用墨西哥人或1月的解决方案使用eval安全检查将会更快。
Str =“[1:3,9:4,7:9)';
%更新的回答
抽搐
k = 1:1
StrParts = regexp (Str,“\ - * \ d + \: *’,“匹配”);
j = 1;
< =长度(StrParts)
如果StrParts {j} = =(结束)“:”
StrParts {j} = str2double (StrParts {j} (1: end-1)): str2double (StrParts {j + 1});
StrParts {j + 1} = [];
j = + 2;
其他的
StrParts {j} = str2double (StrParts {j});
j = + 1;
结束
结束
范围=独特(猫(StrParts {:}));
结束
toc%运行时间是0.926773秒。
%之前的回答
抽搐
k = 1:1
StrParts = cellfun (@ (x)正则表达式(x,“:”,“分裂”),正则表达式(Str,' \ - * \ d +: \ - * \ d + | \ - * \ d +”,“匹配”),“UniformOutput”、假);
NumParts = cellfun (@ (x) str2double (x (1)): str2double (x(结束),StrParts,“UniformOutput”、假);
范围=独特(猫(NumParts {:}));
结束
toc%运行时间是3.294332秒。
% Eval回答
抽搐
k = 1:1
范围=独特(eval (Str));
结束
toc%运行时间是0.352939秒。

登录置评。


沃尔特·罗伯森
沃尔特·罗伯森 2017年9月19日
rng = @ (a, b) strjoin (cellstr (num2str ((str2double (a): str2double (b))”。)”、“);
S =“[1:3、5、13]”
结果= str2double(正则表达式(regexprep(年代,{“\ [”,“]”,”(\ d +): (\ d +) '},{,,“$ {rng ($ 1、$ 2)}”}),“\ s * \ *”,“分裂”));
注意:这段代码假定条目由逗号分隔(可能周围空间)而不是单独空间。
1评论
撒母耳鼠尾草属的植物
我有当我运行此代码测试唐纳德·李(评论者上图)的代码。不幸的是,这段代码慢于eval(),我的目标是优化速度。我试图做一些类似的事情在我自己的,但是我没有使用regexprep ()。我将记住我的未来。非常感谢您输入!

登录置评。


1月
1月 2017年9月19日
只要 eval 处理数字和结肠,不能动态地创建一个变量,它不是邪恶的。你能想到的一个安全检查:
Str =“(1:3 5 7:9)”;
如果~所有(ismember (Str,“0123456789 + -。:”))
错误(“无法处理字符串安全”);
结束
v = eval (Str);
但只要表情像“1 e6”被认为是,问题开始:一个用户可以输入“eeee”并定义相应的功能。那么你需要一些正则表达式检查字符串识别有效数字在科学记数法。但如果这是实现,使用输出或 正则表达式 将会容易得多 eval ing。
看到其他两个答案有建设性的建议。
5个评论
撒母耳鼠尾草属的植物
我理解为什么使用eval()通常让人皱眉头。我从来没有意识到这是多么强大的函数。我一定会限制eval()如果我使用它在未来。谢谢你的这个建议和澄清。

登录置评。

社区寻宝

找到宝藏在MATLAB中央,发现社区如何帮助你!

开始狩猎!