Skip to content

Commit

Permalink
add concat, from_array methods for String (#993)
Browse files Browse the repository at this point in the history
* add string::from_array and string::concat

* add string::join

* remove array::join

* mark Array::join deprecated

* tweak String::concat, remove String::join

* update interface files

* fix doc comments
  • Loading branch information
Yoorkin authored Sep 24, 2024
1 parent eb5c198 commit eca9886
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 37 deletions.
56 changes: 29 additions & 27 deletions array/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,35 @@ pub fn Array::new_with_index[T](length : Int, value : (Int) -> T) -> Array[T] {
}
}

/// Joins the elements of an array into a single string, using the specified separator.
///
/// # Arguments
///
/// * `self` - The array of strings to join.
/// * `sep` - The separator string to insert between each element.
///
/// # Returns
///
/// The joined string.
///
/// @alert deprecated "Use `String::concat` instead"
pub fn join[T : Show](self : Array[T], sep : String) -> String {
let len = self.length()
if len == 0 {
return ""
}
let sep_size = sep.length() * (len - 1)
let self_size = self[0].to_string().length() * (len + 1) // + 1 to avoid allocation in buffer
let size = sep_size + self_size
let buf = Buffer::new(size_hint=size + 1) // + 1 to avoid allocation in buffer
buf.write_string(self[0].to_string())
for i in 1..<len {
buf.write_string(sep)
buf.write_string(self[i].to_string())
}
buf.to_string()
}

pub fn Array::makei[T](length : Int, value : (Int) -> T) -> Array[T] {
if length <= 0 {
[]
Expand Down Expand Up @@ -113,33 +142,6 @@ pub fn Array::shuffle[T](arr : Array[T], ~rand : (Int) -> Int) -> Array[T] {
new_arr
}

/// Joins the elements of an array into a single string, using the specified separator.
///
/// # Arguments
///
/// * `self` - The array of strings to join.
/// * `sep` - The separator string to insert between each element.
///
/// # Returns
///
/// The joined string.
pub fn join[T : Show](self : Array[T], sep : String) -> String {
let len = self.length()
if len == 0 {
return ""
}
let sep_size = sep.length() * (len - 1)
let self_size = self[0].to_string().length() * (len + 1) // + 1 to avoid allocation in buffer
let size = sep_size + self_size
let buf = Buffer::new(size_hint=size + 1) // + 1 to avoid allocation in buffer
buf.write_string(self[0].to_string())
for i in 1..<len {
buf.write_string(sep)
buf.write_string(self[i].to_string())
}
buf.to_string()
}

/// Returns a new array containing the elements of the original array that satisfy the given predicate.
///
/// # Arguments
Expand Down
2 changes: 1 addition & 1 deletion array/array.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl FixedArray {
impl Array {
copy[T](Self[T]) -> Self[T]
from_iter[T](Iter[T]) -> Self[T]
join[T : Show](Self[T], String) -> String
join[T : Show](Self[T], String) -> String //deprecated
last[A](Self[A]) -> A?
makei[T](Int, (Int) -> T) -> Self[T]
map_option[A, B](Self[A], (A) -> B?) -> Self[B]
Expand Down
6 changes: 0 additions & 6 deletions array/array_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,6 @@ test "flatten" {
assert_eq!(vv.length(), 4)
}

test "join" {
let v = [3, 4, 5]
let s = v.join(", ")
assert_eq!(s, "3, 4, 5")
}

test "fold" {
let sum = [1, 2, 3, 4, 5].fold(init=0, fn { sum, elem => sum + elem })
assert_eq!(sum, 15)
Expand Down
6 changes: 3 additions & 3 deletions builtin/builtin.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ impl Hash for Result

impl Hash for Bytes

impl Hash for Hash
impl Hash for $default_impl

impl Hash for Tuple(2)

Expand Down Expand Up @@ -749,6 +749,8 @@ impl Show for Bytes

impl Show for Ref

impl Show for $default_impl

impl Show for Array

impl Show for ArrayView
Expand All @@ -763,8 +765,6 @@ impl Show for Iter2

impl Show for Map

impl Show for Show

impl Show for SourceLoc

impl Show for Tuple(2)
Expand Down
47 changes: 47 additions & 0 deletions string/string.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.

/// Convert char array to string.
///
/// ```
/// String::from_array(['H', 'e', 'l', 'l', 'o']) // "Hello"
/// ```
///
/// Do not convert large datas to `Array[Char]` and build a string with `String::from_array`.
///
/// For efficiency considerations, it's recommended to use `Buffer` instead.
pub fn String::from_array(chars : Array[Char]) -> String {
let buf = Buffer::new(size_hint=chars.length() * 4)
for c in chars {
buf.write_char(c)
}
buf.to_string()
}

/// Concatenate strings.
///
/// ```
/// String::concat(["Hello", ", ", "world!"]) // "Hello, world!"
/// String::concat(["a", "b", "c"], separator=",") // "a,b,c"
/// ```
pub fn String::concat(
strings : Array[String],
~separator : String = ""
) -> String {
let buf = Buffer::new()
if separator == "" {
for s in strings {
buf.write_string(s)
}
} else {
match strings {
[] => ()
[hd, .. as tl] => {
buf.write_string(hd)
for s in tl {
buf.write_string(separator)
buf.write_string(s)
}
}
}
}
buf.to_string()
}

/// Compare two strings.
/// String with longer length is bigger.
/// strings of the same length are compared in lexicalgraphic order.
Expand Down
2 changes: 2 additions & 0 deletions string/string.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ package moonbitlang/core/string
// Types and methods
impl String {
compare(String, String) -> Int
concat(Array[String], ~separator : String = ..) -> String
contains(String, String) -> Bool
contains_char(String, Char) -> Bool
default() -> String
ends_with(String, String) -> Bool
fold[A](String, ~init : A, (A, Char) -> A) -> A
from_array(Array[Char]) -> String
index_of(String, String, ~from : Int = ..) -> Int
is_blank(String) -> Bool
is_empty(String) -> Bool
Expand Down
13 changes: 13 additions & 0 deletions string/string_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

test "String::from_array" {
inspect!(String::from_array(['1', '2', '3', '4', '5']), content="12345")
}

test "String::concat" {
inspect!(String::concat(["123", "456"]), content="123456")
inspect!(
String::concat(["aaa", "bbb", "ccc"], separator=" "),
content="aaa bbb ccc",
)
inspect!(String::concat([], separator=" "), content="")
}

test "default" {
inspect!(@string.default())
}
Expand Down

0 comments on commit eca9886

Please sign in to comment.