简体   繁体   中英

How to multiply strings in Haxe

I'm trying to multiply some string a by some integer b such that a * b = a + a + a... (b times) . I've tried doing it the same way I would in python:

class Test {
    static function main() {
        var a = "Text";
        var b = 4;    
        trace(a * b);    //Assumed Output: TextTextTextText
    }
}

But this raises:

Build failure Test.hx:6: characters 14-15 : String should be Int

There doesn't seem to be any information in the Haxe Programming Cookbook or the API Documentation about multiplying strings, so I'm wondering if I've mistyped something or if I should use:

class Test {
    static function main() {
        var a = "Text";
        var b = 4;
        var c = ""; 

        for (i in 0...b) {
            c = c + a;
        }
        trace(c); // Outputs "TextTextTextText"
    }
}

The numeric multiplication operator * requires numeric types, like integer. You have a string. If you want to multiply a string, you have to do it manually by appending a target string within the loop.

The + operator is not the numeric plus in your example, but a way to combine strings.

You can achieve what you want by operator overloading :

abstract MyAbstract(String) {
    public inline function new(s:String) {
        this = s;
    }

    @:op(A * B)
    public function repeat(rhs:Int):MyAbstract {
        var s:StringBuf = new StringBuf();
        for (i in 0...rhs)
            s.add(this);
        return new MyAbstract(s.toString());
    }
}

class Main {
    static public function main() {
        var a = new MyAbstract("foo");
        trace(a * 3); // foofoofoo
    }
}

Not very short, but array comprehension might help in some situations :

class Test {
    static function main() {
        var a = "Text";
        var b = 4;
        trace( [for (i in 0...b) a].join("") );
        //Output: TextTextTextText
    }
}

See on try.haxe.org .

To build on tokiop's answer , you could also define a times function, and then use it as a static extension.

using Test.Extensions;

class Test {
    static function main() {
        trace ("Text".times(4));
    }
}

class Extensions {
    public static function times (str:String, n:Int) {
        return [for (i in 0...n) str].join("");
    }
}

try.haxe.org demo here

To build on bsinky answer, you can also define a times function as static extension, but avoid the array:

using Test.Extensions;

class Test {
    static function main() {
        trace ("Text".times(4));
    }
}

class Extensions {
    public static function times (str:String, n:Int) {
        var v = new StringBuf();
        for (i in 0...n) v.add(str);
        return v.toString();
    }
}

Demo: https://try.haxe.org/#e5937

StringBuf may be optimized for different targets. For example, on JavaScript target it is compiled as if you were just using strings https://api.haxe.org/StringBuf.html

The fastest method (at least on the JavaScript target from https://try.haxe.org/#195A8 ) seems to be using StringTools._pad .

public static inline function stringProduct ( s : String, n : Int ) {

    if ( n < 0 ) {

        throw ( 1 );

    }

    return StringTools.lpad ( "", s, s.length * n );

}

StringTools.lpad and StringTools.rpad can't seem to decide which is more efficient. It looks like rpad might be better for larger strings and lpad might be better for smaller strings, but they switch around a bit with each rerun. haxe.format.JsonPrinter uses lpad for concatenation, but I'm not sure which to recommend.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM