1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

arrays: add more util functions and tests for them - find_first, find_last, join_to_string (#18784)

This commit is contained in:
encyclopaedia 2023-07-06 22:52:08 -05:00 committed by GitHub
parent 7d6e15fa66
commit e7e5a07aa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 120 additions and 0 deletions

View File

@ -1,5 +1,7 @@
module arrays
import strings
// Common arrays functions:
// - min / max - return the value of the minumum / maximum
// - idx_min / idx_max - return the index of the first minumum / maximum
@ -664,3 +666,53 @@ pub fn carray_to_varray[T](c_array_data voidptr, items int) []T {
unsafe { vmemcpy(v_array.data, c_array_data, total_size) }
return v_array
}
// find_first returns the first element that matches the given predicate
// returns `none`, if there is no match found
// Example: arrays.find_first([1, 2, 3, 4, 5], fn (arr int) bool { arr == 3}) // => 3
pub fn find_first[T](array []T, predicate fn (elem T) bool) ?T {
if array.len == 0 {
return none
}
for item in array {
if predicate(item) {
return item
}
}
return none
}
// find_last returns the last element that matches the given predicate
// returns `none`, if there is no match found
// Example: arrays.find_last([1, 2, 3, 4, 5], fn (arr int) bool { arr == 3}) // => 3
pub fn find_last[T](array []T, predicate fn (elem T) bool) ?T {
if array.len == 0 {
return none
}
for idx := array.len - 1; idx >= 0; idx-- {
item := array[idx]
if predicate(item) {
return item
}
}
return none
}
// join_to_string takes in a custom transform function and joins all elements into a string with
// the specified separator
[manualfree]
pub fn join_to_string[T](array []T, separator string, transform fn (elem T) string) string {
mut sb := strings.new_builder(array.len * 2)
defer {
unsafe { sb.free() }
}
for i, item in array {
x := transform(item)
sb.write_string(x)
unsafe { x.free() }
if i < array.len - 1 {
sb.write_string(separator)
}
}
return sb.str()
}

View File

@ -404,3 +404,71 @@ fn test_map_of_counts() {
assert map_of_counts(['abc', 'def', 'abc']) == {'abc': 2, 'def': 1}
// vfmt on
}
struct FindTest {
name string
age int
}
const test_structs = [FindTest{'one', 1}, FindTest{'two', 2},
FindTest{'three', 3}, FindTest{'one', 4}]
fn test_find_first() {
// element in array
a := [1, 2, 3, 4, 5]
assert find_first[int](a, fn (arr int) bool {
return arr == 3
})? == 3, 'find element couldnt find the right element'
// find struct
find_by_name := find_first(arrays.test_structs, fn (arr FindTest) bool {
return arr.name == 'one'
})?
assert find_by_name == FindTest{'one', 1}
// not found
if _ := find_first(arrays.test_structs, fn (arr FindTest) bool {
return arr.name == 'nothing'
})
{
assert false
} else {
assert true
}
}
fn test_find_last() {
// // element in array
a := [1, 2, 3, 4, 5]
assert find_last[int](a, fn (arr int) bool {
return arr == 3
})? == 3, 'find element couldnt find the right element'
// find struct
find_by_name := find_last(arrays.test_structs, fn (arr FindTest) bool {
return arr.name == 'one'
})?
assert find_by_name == FindTest{'one', 4}
// not found
if _ := find_last(arrays.test_structs, fn (arr FindTest) bool {
return arr.name == 'nothing'
})
{
assert false
} else {
assert true
}
}
fn test_join_to_string() {
assert join_to_string[FindTest](arrays.test_structs, ':', fn (it FindTest) string {
return it.name
}) == 'one:two:three:one'
assert join_to_string[FindTest](arrays.test_structs, '', fn (it FindTest) string {
return it.name
}) == 'onetwothreeone'
assert join_to_string[int]([]int{}, ':', fn (it int) string {
return '1'
}) == ''
}