【问题标题】:Adding the replaceAll method to the ActionScript String class将 replaceAll 方法添加到 ActionScript String 类
【发布时间】:2010-11-03 09:18:27
【问题描述】:

在将替换所有功能添加到我的 Flex 项目中时,我需要一些帮助。我希望以尽可能自然的方式来做这件事。

我想要实现的是能够运行这段代码(使用 Flex 编译器)"aabbaaba".replaceAll("b","c") 并获得 "aaccaaca"。我还想链接replaceAll 调用。
注意:我实际上不会用cs 替换bs,而是在编码时不知道的各种字符串!

我不想要的:
1. 使用带有全局标志的正则表达式。要替换的标记是确定的广告运行时间,将它们转换为正则表达式并不简单。
2. 使用StringUtil.replace 方法。这是一个静态方法,链接很丑。
3.链split和join。因为在阅读代码时可能会让其他人感到困惑。
4.禁用严格类型检查。我想对我的其余代码进行类型检查。


这是我目前所拥有的:

String.prototype.replaceAll = function(replace:String, replaceWith:String):String{
    return this.split(replace).join(replaceWith);
}

并且可以这样调用:

"aababacaaccb"["replaceAll"]("b", "c")["replaceAll"]("c", "a");

另外,是否有反对通过原型扩展对象的建议? 我也会接受一个强烈反对通过原型扩展 String 对象的答案。

谢谢你,
阿林

【问题讨论】:

  • 如果投反对票的人能够证明他们的行为是正当的,以便我能够改进问题,那就太好了。谢谢。
  • wtf?你不想使用正则表达式?那么即使进行字符串搜索/替换又有什么意义呢?你正在替换一个字符串。使用字符串函数。在正则表达式中使用变量并不难……
  • @Daniel 你可能不明白这个问题。或者没有仔细阅读。我想要做的是拥有StringUtil.replace 所做的事情,但直接作为我的 String 对象上的方法。我没有模式,我只有一个要替换的字符串。有很多方法可以做到这一点,但我想要一些 clean (如字符串方法)或尽可能干净(如 9re 或 Juan Pablo Califano 建议的)。
  • @Daniel 你也没有连贯。我不是指你英语不好(这很奇怪,因为你的个人资料显示你来自纽约),而是指你自相矛盾的事实。例如:“你不想使用正则表达式?”与“您正在替换字符串。使用字符串函数。”。
  • 好吧,您似乎已经回答了自己的问题。你说你想替换,但你不想使用正则表达式,也不想加入,也不想拆分,也不想 StringUtil.replace,也不想类型检查。 wtf。 StringUtil.prototype.replaceAll = function(r:String, w:String):String { return this.replace(new RegExp(r, 'g'), w); )

标签: apache-flex actionscript-3 oop actionscript


【解决方案1】:

第二个答案是这样的:

为String编写包装类StringEx,你可以定义replaceAll像这样被链接

public function replaceAll(replace:String, replaceWith:String):StringEx {
   string = string.replace(new RegExp(replace, 'g'), replaceWith);
   return this;
}

通过提供 toString(),您可以轻松地将 StringEx 对象更改为 String

var result:String = "" + new StringEx("aaccaaca").replaceAll('b', 'c').replaceAll('c', 'a');

你可以在这里获得完整版:OOP way of prototype extension - wonderfl build flash online

【讨论】:

  • 这可能是一种替代方案,因为您只需要包装一次,但我希望有一个原型解决方案,或者至少回答证明我想要的东西不能或不应该是达到了。
【解决方案2】:

我认为您已经获得了所有可能的技术答案。我将详细说明我认为处理这种语言的最佳方式。

不推荐在诸如 AS3 之类的 OOP 语言中使用原型(主要是因为它们不符合封装性)。您暗示您不想要“让他人感到困惑”的东西(与 split.join 相关);好吧,AS3 中的原型非常混乱。 举个例子,原型声明可以在代码中的任何地方完成,因此它应该驻留在哪里并不明显。如果“其他人”在您的代码中遇到“foo”.replaceAll(),那么在哪里可以找到该方法并检查它的实际作用并不明显。

静态函数修正了这一点并且非常简单。当然,你需要一个额外的参数,而且你不能真正正确地链接,但这是一件坏事吗?

如果您需要性能,split.join 是不二之选。我敢打赌,比起原型的使用,更多的 AS3 开发者知道 split.join。

另一方面,我认为最语义化和最实用的方法是使用自己的语言方法(因此我之前的回答)。您正在尝试用 AS3 中的另一个字符串替换字符串中的所有针,为此,该语言具有带全局标志的 String::replace 方法。我很确定有一种方法可以轻松解析和使用正则表达式中的任何字符串。

我同意在某些情况下可能需要辅助方法(如 replaceAll),但我强烈建议您不要使用原型,而是使用更标准的方法,如 StringUtil.replace。

【讨论】:

  • 您不使用原型可能是对的,我会接受这个答案。至于将字符串转换为与这些字符串完全匹配的正则表达式等价物,这样做意味着在每个替换标记上调用一个静态函数,我认为这将等同于此处发布的其他解决方案。我想通过这个问题找出是否可以,并且可以向现有对象类型添加功能。似乎答案是:不。谢谢你的贡献!
【解决方案3】:

我不想要的: 1. 使用带全局标志的正则表达式

为什么不呢?对于简单的字符串替换非常简单且高效:

"aababacaaccb".replace(/b/g, "c");

或者如果您愿意:

var needle:String="b";
"aababacaaccb".replace(new RegExp(needle,"g"), "c");

我不建议为此使用原型,它不是非常 OOP 也不是标准......对于这样一个简单的操作来说感觉太hacky了。

【讨论】:

  • 你可能不明白,我使用a、b 和c 只是为了说明我想要什么。我认为没有必要说出来。我希望能够用任何字符串替换任何字符串。我编辑了问题。
  • 您也不能使用RegExp(needle,"g") 来转换正则表达式中找到它的字符串(因为特殊的正则表达式符号)。你的答案是迄今为止最糟糕的,你甚至没有尝试过。我不明白为什么有人会投票...
  • 你对我的口味有点太居高临下......虽然你是对的,但对于任何字符串来说都不是那么直截了当,但我相信你可以解决这个问题(我会使用 split .join BTW)...
【解决方案4】:

我想不出满足您发布的 4 个要求的方法。但我认为,如果您的主要目标是一次性替换各种标记(您希望通过链接调用实现的目标)同时能够使用任何字符串作为标记,您可以尝试这样的事情:

public class StringUtil {
    public static function replaceAll(source:String,map:Object):String {
        for(var replaceToken:String in map) {
            source = source.split(replaceToken).join(map[replaceToken]);
        }
        return source;
    }
}

var str:String = "a1ccca111a";

str = StringUtil.replaceAll(str,{
    'a' : 'b',
    '1' : '2'
});
trace(str);

请记住一个警告。对于 Object 对象,不能保证顺序。在大多数情况下,这并不重要,但如果在您的情况下,您可以改用数组,并在每个插槽中存储令牌及其替换(例如作为对象)。

【讨论】:

  • 有趣的方法。 “我想不出办法来满足你发布的 4 个要求。”你这么说是因为字面上你想不出办法,还是你真的认为无法将replaceAll 添加到 String 对象?
  • @Alin。好吧,我的意思是我自己找不到方法。而且可能没有(但也许有人找到了,谁知道)。如果你走原型路线,你会失去你所知道的类型检查。对于所有使用此方法的代码;也许有一种方法可以避免“其余代码”出现这种情况,但肯定会涉及(如果可能的话)。
  • (cont) 扩展字符串是不可能的,因为类是最终的,所以使用对象实例(用于方法链接等)将需要额外的样板(你可以有某种包装器,但它如果需要字符串,则不能使用;这是我认为您将获得大部分样板的地方)。所以我认为在特定情况下使用实用程序静态方法是最简单、直接和直观的选择。
【解决方案5】:

"aabbaaba".split('b').join('c') 返回“aaccaaca”

UPD:
我想知道为什么它对你来说是不可接受的(但是它不支持正则表达式):它工作得非常快(在严重的循环中检查它)并且完全符合你的要求。

还有一些您的黑名单中没有提到的解决方案(顺便说一句,静态函数比弄乱原型更好 - 恕我直言):

  • 您可以仅使用replaceAll 方法和super() 调用来扩展String 类。如果您检查(myStringInstance is String),此类的实例将返回true
  • 和另一个解决方案:创建一个包装器而不是扩展:一个将为您存储一个字符串的类提供额外的功能(虽然我无法想象一个字符串),并且可能将它的一些属性设置为只读。或者它可能只有一个 getter 和 setter

【讨论】:

  • 这就是他(无论如何)不想使用的:“我不想:3.链拆分和加入”
  • “btw 静态函数比弄乱原型更好” - 你能详细说明一下吗?
  • @splash 我不想要 split+join 因为组合的作用并不明显。这对我来说很明显,因为我知道StringUtil.replace 是如何实现的,但对于其他将阅读我的代码的人来说可能不是。
【解决方案6】:

我有两个答案给你。第一个是你想要的。但我推荐第二个。

在 flex 中启用原型非常简单,可以通过设置 flex-config 来完成

ReplaceAllTest.as

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    public class ReplaceAllTest extends Sprite
    {
        public function ReplaceAllTest() 
        {
            var tf:TextField = new TextField;
            String.prototype.replaceAll = function(replace:String, replaceWith:String):String{
                return this.split(replace).join(replaceWith);
            }
            // now the strict mode is off compiler does NOT warn the following code
            tf.text = "aababacaaccb".replaceAll("b", "c")
                                    .replaceAll("c", "a");
            addChild(tf);
        }
    }
}

ReplaceAllTest-config.xml

<?xml version="1.0" encoding="utf-8" ?>
<flex-config>
    <compiler>
       <as3>false</as3>
       <es>true</es>
       <strict>false</strict>
    </compiler>
    <static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
</flex-config>

我仍然不鼓励这种方式,因为启用原型设计和关闭严格模式会减慢您的代码速度。

【讨论】:

  • 我对严格类型检查说了什么?我不想要那个。我知道该怎么做,但我希望它在我的其余代码中处于活动状态。
  • 哦,对不起!我犯了一个错误。但是 compiler.es 必须设置为 compiler.strict false: livedocs.adobe.com/flex/3/html/…
  • @Alin Purcaru。考虑到您要求其他人帮助 您 解决 your 问题(并且他们试图帮助您而没有得到任何东西),我认为您有点过于咄咄逼人作为回报)。
  • @Juan 我知道我是,我为此道歉,但这是一个性格问题,而不是编程问题。我认为(还没有)一个堆栈交换站点可以解决这个问题:)。我想当我看到完全符合我明确表示我不想要的答案时,我会感到沮丧。至于问题部分,我在发布问题之前使用了[] 访问权限。所以你不能真的说我需要快速解决一个问题,而是我想听听其他解决这个问题的程序员的一些有能力的意见。
  • @Alin。好的,我只是想提一下,友善并没有什么坏处(即使您发现给定的答案不令人满意)。无论如何,我发布了一个可能的选项。
【解决方案7】:

我知道这是一个旧线程,但这是我想出的可以做任何常规字符串的方法。

    public static function replaceAll(p_string:String, p_search:String, p_replaceWith:String):String{

    //Dummy Control
        if(p_string == null)
            return '';

    //Iterates through the string from right to left so we don't go over what we are changing.
        var index:int = p_string.lastIndexOf(p_search);
        while(index != -1){

        //Splits the string at the index
            p_string = p_string.slice(0, index) + p_replaceWith + p_string.slice(index+p_search.length);

        //Attempts to find the next index
            index = p_string.lastIndexOf(p_search, index-1);//We -1 so we always move down the line
        }

    //Returns the modified p_string
        return p_string;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 2011-01-24
    • 2015-04-28
    • 2012-06-07
    • 1970-01-01
    • 2022-08-18
    • 2011-07-28
    相关资源
    最近更新 更多