blob: 780b4ac0f15062843b7aa0abf98d25ce6296c224 [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package slice
import (
"reflect"
"github.com/aclements/go-gg/generic"
)
// Select returns a slice w such that w[i] = v[indexes[i]].
func Select(v T, indexes []int) T {
switch v := v.(type) {
case []int:
res := make([]int, len(indexes))
for i, x := range indexes {
res[i] = v[x]
}
return res
case []float64:
res := make([]float64, len(indexes))
for i, x := range indexes {
res[i] = v[x]
}
return res
case []string:
res := make([]string, len(indexes))
for i, x := range indexes {
res[i] = v[x]
}
return res
}
rv := reflectSlice(v)
res := reflect.MakeSlice(rv.Type(), len(indexes), len(indexes))
for i, x := range indexes {
res.Index(i).Set(rv.Index(x))
}
return res.Interface()
}
// SelectInto assigns out[i] = in[indexes[i]]. in and out must have
// the same types and len(out) must be >= len(indexes). If in and out
// overlap, the results are undefined.
func SelectInto(out, in T, indexes []int) {
// TODO: Maybe they should only have to be assignable?
if it, ot := reflect.TypeOf(in), reflect.TypeOf(out); it != ot {
panic(&generic.TypeError{it, ot, "must be the same type"})
}
switch in := in.(type) {
case []int:
out := out.([]int)
for i, x := range indexes {
out[i] = in[x]
}
return
case []float64:
out := out.([]float64)
for i, x := range indexes {
out[i] = in[x]
}
return
case []string:
out := out.([]string)
for i, x := range indexes {
out[i] = in[x]
}
return
}
inv, outv := reflectSlice(in), reflectSlice(out)
for i, x := range indexes {
outv.Index(i).Set(inv.Index(x))
}
}