首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字符串中的匹配括号

字符串中的匹配括号
EN

Stack Overflow用户
提问于 2011-04-25 07:17:36
回答 9查看 3.8K关注 0票数 14

在字符串中匹配括号的最有效或最优雅的方法是什么,如:

代码语言:javascript
复制
"f @ g[h[[i[[j[2], k[[1, m[[1, n[2]]]]]]]]]] // z"

为了识别和用单字符形式替换[[ Part ]]括号?

我想要:

所有其他内容都完好无损,例如前缀@和后缀//窗体完好无损。

数学语法对不熟悉的人的解释:

函数对参数使用单个方括号:func[1, 2, 3]

部件索引使用双方括号:list[[6]]或单字符Unicode双括号:list〚6〛完成。

我的目的是在ASCII文本字符串中标识匹配的[[ ]]表单,并将其替换为Unicode字符〚 〛

EN

回答 9

Stack Overflow用户

发布于 2011-04-25 09:23:30

好吧,这是另一个答案,稍微短一点:

代码语言:javascript
复制
Clear[replaceDoubleBrackets];
replaceDoubleBrackets[str_String, openSym_String, closeSym_String] := 
Module[{n = 0},
  Apply[StringJoin, 
   Characters[str] /. {"[" :> {"[", ++n}, 
     "]" :> {"]", n--}} //. {left___, {"[", m_}, {"[", mp1_}, 
      middle___, {"]", mp1_}, {"]", m_}, right___} /; 
       mp1 == m + 1 :> {left, openSym, middle, 
        closeSym, right} /. {br : "[" | "]", _Integer} :> br]]

示例:

代码语言:javascript
复制
In[100]:= replaceDoubleBrackets["f[g[h[[i[[j[2], k[[1, m[[1, n[2]]]]]]]]]]]", "(", ")"]

Out[100]= "f[g[h(i(j[2], k(1, m(1, n[2]))))]]"

编辑

如果要用所指示的符号替换双括号,也可以使用Mathematica内置设施:

代码语言:javascript
复制
Clear[replaceDoubleBracketsAlt];
replaceDoubleBracketsAlt[str_String] :=
  StringJoin @@ Cases[ToBoxes@ToExpression[str, InputForm, HoldForm],
     _String, Infinity]

In[117]:= replaceDoubleBracketsAlt["f[g[h[[i[[j[2], k[[1, m[[1, n[2]]]]]]]]]]]"]

Out[117]= f[g[h[[i[[j[2],k[[1,m[[1,n[2]]]]]]]]]]]

结果不会在这里正确显示,但它是一个Unicode字符串,包含您请求的符号。

票数 5
EN

Stack Overflow用户

发布于 2011-04-25 14:18:04

当我编写第一个解决方案时,我没有注意到您只是想用字符串中的[[替换,而不是表达式。您可以始终使用HoldFormDefer作为

但是我想您已经知道了,您希望表达式是一个字符串,就像输入(上面的ToString@不起作用)

由于到目前为止,所有的答案都集中在字符串操作上,所以我将采用一种数字方法,而不是与字符串搏斗,这对我来说更自然。[的字符代码为91,]为93。因此,请执行以下操作

给出括号作为0/1向量的位置。我已经否定了结尾括号,只是为了帮助思考过程,并供以后使用。

注意:我只检查了91和93的可分性,因为我当然不期望您输入以下任何字符,但是如果出于某种原因,您可以很容易地使用91或93相等的布尔列表来AND上面的结果。

由此,可以找到Part的第一个双括号对的位置

事实上,在mma中,表达式不以[开头,而且两个以上的[不能连续出现,因为在上面的计算中已经隐式假定了[[[...

现在,结束对的实现更加困难,但理解起来却很简单。其想法如下:

  • 对于closeBracket中的每个非零位置,例如i,转到openBracket中的相应位置,并在其左侧找到第一个非零位置(例如j)。
  • 设置doubleCloseBrackets[[i-1]]=closeBracket[[i]]+openBracket[[j]]+doubleOpenBrackets[[j]]
  • 你可以看到,doubleCloseBracketsdoubleOpenBrackets的对应物,在Part]]对的第一个位置上是非零的。

因此,现在我们有一组布尔位置,用于第一个开括号。我们只需将charCode中的对应元素替换为等效的,类似地,用第一个近括号的布尔位置,我们将charCode中的相应元素替换为等效的

最后,通过删除被更改的元素旁边的元素,您可以使用[[]]替换已修改的字符串为〚 〛

注2:

我的很多MATLAB习惯已经在上面的代码中慢慢出现了,而且在Mathematica中也不完全是惯用的。然而,我认为这种逻辑是正确的,而且是可行的。我将让您来优化它(我认为您可以取消Do[])并使它成为一个模块,因为我需要更长的时间才能完成它。

代码作为文本

代码语言:javascript
复制
Clear["Global`*"]
str = "f[g[h[[i[[j[2], k[[1, m[[1, n[2]]]]]]]]]]]";
charCode = ToCharacterCode@str;
openBracket = Boole@Divisible[charCode, First@ToCharacterCode["["]];
closeBracket = -Boole@
    Divisible[charCode, First@ToCharacterCode["]"]];
doubleOpenBracket = 
  Append[Differences@Accumulate[openBracket], 0] openBracket;
posClose = Flatten@Drop[Position[closeBracket, Except@0, {1}], 1];

doubleCloseBracket = ConstantArray[0, Dimensions@doubleOpenBracket];
openBracketDupe = openBracket + doubleOpenBracket;
Do[
  tmp = Last@
    Flatten@Position[openBracketDupe[[1 ;; i]], Except@0, {1}];
  doubleCloseBracket[[i - 1]] = 
   closeBracket[[i]] + openBracketDupe[[tmp]];
  openBracketDupe[[tmp]] = 0;,
  {i, posClose}];

changeOpen = 
  Cases[Range[First@Dimensions@charCode]  doubleOpenBracket, Except@0];
changeClosed = 
  Cases[Range[First@Dimensions@charCode]  doubleCloseBracket, 
   Except@0];
charCode[[changeOpen]] = ToCharacterCode["\[LeftDoubleBracket]"];
charCode[[changeClosed]] = ToCharacterCode["\[RightDoubleBracket]"];
FromCharacterCode@
 Delete[Flatten@charCode, 
  List /@ (Riffle[changeOpen, changeClosed] + 1)]
票数 5
EN

Stack Overflow用户

发布于 2011-04-25 22:41:46

这是我的尝试。由于特殊字符的存在,粘贴的ASCII代码非常不可读,所以我首先提供了它在MMA中的外观的图片。

基本上,它所做的是:方括号总是唯一可识别为单或双。问题就在括号内。开始括号总是有模式字符串的字符-不含括号+[或[.这是不可能有一个[后面[或反之亦然,没有其他字符之间(至少,不是在无错误的代码)。

因此,我们使用这个挂钩,并开始寻找特定的匹配括号,即那些没有任何其他括号之间。因为我们知道这种类型,或者“.”或者“[.]”,我们可以用双括号符号替换后一个,用未使用的字符代替前者(我使用笑脸)。这样做是为了使他们不再在模式匹配过程的下一次迭代中扮演角色。

我们重复,直到所有括号被处理,最后笑脸再次转换为单一括号。

你看,这种解释比代码所用的字符更多;-)。

Ascii:

代码语言:javascript
复制
s = "f @ g[hh[[i[[jj[2], k[[1, m[[1, n[2]]]]]]]]]] // z";

myRep[s_String] :=
 StringReplace[s,
  {
   Longest[y : Except["[" | "]"] ..] ~~ "[" ~~ 
     Longest[x : Except["[" | "]"] ..] ~~ "]" :> 
    y <> "\[HappySmiley]" <> x <> "\[SadSmiley]",
   Longest[y : Except["[" | "]"] ..] ~~ "[" ~~ Whitespace ... ~~ "[" ~~
      Longest[x : Except["[" | "]"] ..] ~~ "]" ~~ Whitespace ... ~~ 
     "]" :> y <> "\[LeftDoubleBracket]" <> x <> "\[RightDoubleBracket]"
   }
  ]

StringReplace[FixedPoint[myRep, s], {"\[HappySmiley]" -> "[","\[SadSmiley]" -> "]"}]

哦,Whitespace部分是因为在数学中,两个括号不一定是相邻的。a[ [1] ]a[[1]]一样合法。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5776158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档