我有一个字符串列表
store = {
componentStore: [[1, 1, 1, 1], [1, 1], [1, 0, 0, 0]]
}
我想执行一个简单的mapReduce操作,这样我
将每个字符串映射到不同的字符串,让我们说elems := [n]string{...}
使用分隔符将所有字符串缩减为一个字符串,例如string -> $string
总而言之:{s1, s2, s3} -> s1@s2@s3
最好的方法是什么?
我正在寻找效率和可读性
奖励积分,如果它的通用性不仅适用于字符串
答案 0 :(得分:2)
对于仅映射列表,除了遍历每个字符串之外,您没有太多选择。如果变换算法耗时并且您需要速度,则可以考虑拆分作业并使用go例程。最后,您可以使用strings.Join函数,它具有指定分隔符的选项,这通常可以有效地执行reduce部分。数据集的大小也可以作为考虑因素,对于较大的列表,您可能希望将性能与strings.Join和您自己的自定义算法进行比较,看看是否要使用多个go例程/通道来实现您想要的。
答案 1 :(得分:1)
如果您不需要单独执行这两项操作,只需使用strings.Join()
即可达到最终结果:
package main
import (
"fmt"
"strings"
)
func main() {
a := []string{"a", "b", "c"}
p := "$"
fmt.Println(p + strings.Join(a[:], "@"+p))
}
打印$a@$b@$c
答案 2 :(得分:0)
Go显然不是函数式编程语言。
使用for循环进行映射和缩小。
a := []string{"a", "b", "c"}
result := "initvalue"
for n, i := range a {
result += i + string(n)
}
答案 3 :(得分:0)
如果您不打算在 map 函数中执行任何类型的IO操作(意味着它们只进行一些计算),那么使它并发会使它变得更慢,即使你是做一些IO,你应该做基准测试。并发性不会使事情变得更快,有时会增加不必要的复杂性。在许多情况下,只需一个简单的 for 循环即可。
如果这里的 map 函数是IO绑定的,或者正在进行某种计算,这些计算可以从并发中获益,那么解决方案可能会有所不同。例如,NATS可用于超越一台计算机并分配工作负载。
这是一个相对简单的样本。减少阶段不是多阶段并且阻塞:
import (
"fmt"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/assert"
)
type elem struct {
index int
value interface{}
}
func feed(elems []interface{}) <-chan elem {
result := make(chan elem)
go func() {
for k, v := range elems {
e := elem{
index: k,
value: v,
}
result <- e
}
close(result)
}()
return result
}
func mapf(
input <-chan elem,
mapFunc func(elem) elem) <-chan elem {
result := make(chan elem)
go func() {
for e := range input {
eres := mapFunc(e)
result <- eres
}
close(result)
}()
return result
}
// is blocking
func reducef(
input <-chan elem,
reduceFunc func([]interface{}) interface{}) interface{} {
buffer := make(map[int]interface{})
l := 0
for v := range input {
buffer[v.index] = v.value
if v.index > l {
l = v.index
}
}
data := make([]interface{}, l+1)
for k, v := range buffer {
data[k] = v
}
return reduceFunc(data)
}
func fanOutIn(
elemFeed <-chan elem,
mapFunc func(elem) elem, mapCount int,
reduceFunc func([]interface{}) interface{}) interface{} {
MR := make(chan elem)
wg := &sync.WaitGroup{}
for i := 0; i < mapCount; i++ {
mapResult := mapf(elemFeed, mapFunc)
wg.Add(1)
go func() {
defer wg.Done()
for v := range mapResult {
MR <- v
}
}()
}
go func() {
wg.Wait()
close(MR)
}()
return reducef(MR, reduceFunc)
}
func Test01(t *testing.T) {
elemFeed := feed([]interface{}{1, 2, 3})
finalResult := fanOutIn(
elemFeed,
func(e elem) elem {
return elem{
index: e.index,
value: fmt.Sprintf("[%v]", e.value),
}
},
3,
func(sl []interface{}) interface{} {
strRes := make([]string, len(sl))
for k, v := range sl {
strRes[k] = v.(string)
}
return strings.Join(strRes, ":")
})
assert.Equal(t, "[1]:[2]:[3]", finalResult)
}
由于它使用interface{}
作为元素类型,因此可以进行推广。