Given this code:
var a map[string][][]int
var aa map[string][][]int = map[string][][]int{"a": [][]int{{10, 10}, {20, 20}}}
var bb map[string][][]int = map[string][][]int{"b": [][]int{{30, 30}, {40, 40}}}
fmt.Println(aa) // >> map[a:[[10 10] [20 20]] b:[[30 30] [40 40]]]
how do I know if '[30, 30]' is in 'aa'?
I want to check, whether 'aa' has '[30 30]'.
You'll have to iterate over the contents of your map to check whether an element is contained in that map or not.
For example:
target := []int{30, 30}
for _, v := range myMap {
for _, sub := range v {
if len(sub) == len(target) && sub[0] == target[0] && sub[1] == target[1] {
fmt.Println("yeah")
}
}
}
With myMap as aa you'll get no output, and with myMap as bb you'll get "Yeah" printed.
If your inner-most slices get longer, you should do the check step as a loop as well instead of hard-coded like that.
Maps are only indexed by key. This means its cheap and easy (ideally constant time complexity) to find a or b, but its harder to look for a value (linear time complexity).
Therefore, it's a few for loops:
func find(searchFor [][]int, m map[string][][]int) bool {
for _, v := range m {
if sliceEq(v, searchFor) {
return true
}
}
return false
}
func sliceEq(a, b [][]int) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
I am having problems assigning a pointer to a map. Maybe this is a bug in Go? Or maybe I am just doing something wrong. The code is here on the playground as well, https://play.golang.org/p/p0NosPtkptz
Here is some super simplified code that illustrates the problem. I am creating an object called collections that has two collection objects in it. I am then looping through those collections and assigning them to a map where the key in the map is the collection ID.
package main
import (
"fmt"
)
type collection struct {
ID string
Name string
}
type collections struct {
Collections []collection
}
type cache struct {
Index int
Collections map[string]*collection
}
func main() {
var c cache
c.Collections = make(map[string]*collection)
// Create 2 Collections
var col1, col2 collection
col1.ID = "aa"
col1.Name = "Text A"
col2.ID = "bb"
col2.Name = "Test B"
// Add to Collections
var cols collections
cols.Collections = append(cols.Collections, col1)
cols.Collections = append(cols.Collections, col2)
fmt.Println("DEBUG Collections Type", cols)
i := 0
for k, v := range cols.Collections {
c.Index = i
c.Collections[v.ID] = &v
fmt.Println("DEBUG k", k)
fmt.Println("DEBUG v", v)
i++
}
fmt.Println("Collection 1", c.Collections["aa"].ID)
fmt.Println("Collection 2", c.Collections["bb"].ID)
fmt.Println(c)
}
The output from this playground code looks like:
DEBUG Collections Type {[{aa Text A} {bb Test B}]}
DEBUG k 0
DEBUG v {aa Text A}
DEBUG k 1
DEBUG v {bb Test B}
Collection 1 bb
Collection 2 bb
{1 map[aa:0x1040a0f0 bb:0x1040a0f0]}
So it seems like the map is for some reason getting the same pointer for each entry. All of the "DEBUG" lines print out what I would expect. However, the three print lines at the very end, do not. Collection 1 should be "aa" not "bb".
When you are putting &v into c.Collections[v.ID], you are actually assigning same address of loop variable v.
This address finally holds the last value of your list. That's why you are getting bb Test B for all key.
Print these value and you will see same address.
fmt.Printf("%p\n", c.Collections["aa"])
fmt.Printf("%p\n", c.Collections["bb"])
And by copying it to a new variable in the loop scope, the issue is solved. Each step in the loop you will put a new and unique address into the cache.
for k, v := range cols.Collections {
coll := v
c.Collections[v.ID] = &coll
fmt.Println("DEBUG k", k)
fmt.Println("DEBUG v", v)
i++
}
Unfortunately, the code in the first answer has an error - a pointer to a local variable coll:
for k, v := range cols.Collections {
coll := v
c.Collections[v.ID] = &coll
Just try to change a property value of a collection:
cols.Collections[0].Name = "Text C"
fmt.Println("Collection 1", cols.Collections[0].Name)
fmt.Println("Collection 1", c.Collections["aa"].Name)
// Collection 1 Text C
// Collection 1 Text A
But the another code will print an expected result:
for k, v := range cols.Collections {
c.Index = i
p := &cols.Collections[k]
c.Collections[v.ID] = p
....
cols.Collections[0].Name = "Text C"
fmt.Println("Collection 1", cols.Collections[0].Name)
fmt.Println("Collection 1", c.Collections["aa"].Name)
// Collection 1 Text C
// Collection 1 Text C
The answer about same pointer is a map contains the address of a variable v, but not array items.
for k, v := range cols.Collections {
......
c.Collections[v.ID] = &v
A right solution is storing a pointer to array, but not a value.
type collections struct {
Collections []*collection
}
cols.Collections = append(cols.Collections, &col1)
cols.Collections = append(cols.Collections, &col2)
Or get address of map item (as the answer higher)
for k, v := range cols.Collections {
c.Index = i
p := &cols.Collections[k]
c.Collections[v.ID] = p
I'm dealing with numbers that require a big.Float type, and I need to divide them. I'm aware that big.Int has a .Div() function, but if I'm correct, that truncates the value and loses the precision I get from using big.Float.
Relevant code
func e(prec int64) (res *big.Float) {
res = big.NewFloat(float64(1.0))
base := big.NewInt(prec)
for i := base; i.Cmp(big.NewInt(int64(0))) == 1; _ = i.Sub(i, big.NewInt(1)) {
d := big.NewFloat(float64(1.0))
_ = d.Div(fact(i)) // error here
res.Add(d)
}
return
}
Use Float.Quo for big.Float division:
x, y := big.NewFloat(10), big.NewFloat(3)
z := new(big.Float).Quo(x, y)
http://play.golang.org/p/GRPAKQNkq0
I am working on creating a struct that represents a Matrix with methods to manipulate the data within the type. There are two methods that I use as an example to set a single row or column to a specific value. Here is a snippet of my code:
type Matrix struct {
Height, Width int
data [][]int
}
func NewMatrix(nrows, ncols int) (mat *Matrix) {
mat = new(Matrix)
mat.Height = nrows
mat.Width = ncols
mat.data = make([][]int, nrows)
for i := range mat.data {
mat.data[i] = make([]int, ncols)
for j := range mat.data[i]{
mat.data[i][j] = 0
}
}
return
}
func (mat *Matrix) SetCol(col, val int) {
for i := 0; i < mat.Height; i++ {
mat.data[i][col] = val
}
}
func (mat *Matrix) SetRow(row, val int) {
for i := 0; i < mat.Width; i++ {
mat.data[row][i] = val
}
}
When I use this Matrix type and manipulating the data attribute like so:
mat := NewMatrix(33,33)
mat.SetCol(2, 3)
mat.SetRow(2, 3)
I am finding that the data attribute of the Matrix instance is being set within the method SetCol but once it returns from this method the data appears to be the empty matrix that I initialized it to.
Why is the data attribute that I am manipulating in the method not persisting past the lifetime of the method call? How can I fix this?
Edit
I found out that the issue was that I was instantiating a new instance of a Matrix on each iteration in a loop which is why the matrix always appeared to be empty after I manipulated it with SetCol and SetRow. So the question is not really valid.
As a silly toy example, suppose
x=4.5
w=c(1,2,4,6,7)
I wonder if there is a simple R function that finds the index of the closest match to x in w. So if foo is that function, foo(w,x) would return 3. The function match is the right idea, but seems to apply only for exact matches.
Solutions here (e.g. which.min(abs(w - x)), which(abs(w-x)==min(abs(w-x))), etc.) are all O(n) instead of log(n) (I'm assuming that w is already sorted).
R>findInterval(4.5, c(1,2,4,5,6))
[1] 3
will do that with price-is-right matching (closest without going over).
You can use data.table to do a binary search:
dt = data.table(w, val = w) # you'll see why val is needed in a sec
setattr(dt, "sorted", "w") # let data.table know that w is sorted
Note that if the column w isn't already sorted, then you'll have to use setkey(dt, w) instead of setattr(.).
# binary search and "roll" to the nearest neighbour
dt[J(x), roll = "nearest"]
# w val
#1: 4.5 4
In the final expression the val column will have the you're looking for.
# or to get the index as Josh points out
# (and then you don't need the val column):
dt[J(x), .I, roll = "nearest", by = .EACHI]
# w .I
#1: 4.5 3
# or to get the index alone
dt[J(x), roll = "nearest", which = TRUE]
#[1] 3
See match.closest() from the MALDIquant package:
> library(MALDIquant)
> match.closest(x, w)
[1] 3
x = 4.5
w = c(1,2,4,6,7)
closestLoc = which(min(abs(w-x)))
closestVal = w[which(min(abs(w-x)))]
# On my phone- please pardon typos
If your vector is lengthy, try a 2-step approach:
x = 4.5
w = c(1,2,4,6,7)
sdev = sapply(w,function(v,x) abs(v-x), x = x)
closestLoc = which(min(sdev))
for maddeningly long vectors (millions of rows!, warning- this will actually be slower for data which is not very, very, very large.)
require(doMC)
registerDoMC()
closestLoc = which(min(foreach(i = w) %dopar% {
abs(i-x)
}))
This example is just to give you a basic idea of leveraging parallel processing when you have huge data. Note, I do not recommend you use it for simple & fast functions like abs().
To do this on character vectors, Martin Morgan suggested this function on R-help:
bsearch7 <-
function(val, tab, L=1L, H=length(tab))
{
b <- cbind(L=rep(L, length(val)), H=rep(H, length(val)))
i0 <- seq_along(val)
repeat {
updt <- M <- b[i0,"L"] + (b[i0,"H"] - b[i0,"L"]) %/% 2L
tabM <- tab[M]
val0 <- val[i0]
i <- tabM < val0
updt[i] <- M[i] + 1L
i <- tabM > val0
updt[i] <- M[i] - 1L
b[i0 + i * length(val)] <- updt
i0 <- which(b[i0, "H"] >= b[i0, "L"])
if (!length(i0)) break;
}
b[,"L"] - 1L
}
NearestValueSearch = function(x, w){
## A simple binary search algo
## Assume the w vector is sorted so we can use binary search
left = 1
right = length(w)
while(right - left > 1){
middle = floor((left + right) / 2)
if(x < w[middle]){
right = middle
}
else{
left = middle
}
}
if(abs(x - w[right]) < abs(x - w[left])){
return(right)
}
else{
return(left)
}
}
x = 4.5
w = c(1,2,4,6,7)
NearestValueSearch(x, w) # return 3
Based on #neal-fultz answer, here is a simple function that uses findInterval():
get_closest_index <- function(x, vec){
# vec must be sorted
iv <- findInterval(x, vec)
dist_left <- x - vec[ifelse(iv == 0, NA, iv)]
dist_right <- vec[iv + 1] - x
ifelse(! is.na(dist_left) & (is.na(dist_right) | dist_left < dist_right), iv, iv + 1)
}
values <- c(-15, -0.01, 3.1, 6, 10, 100)
grid <- c(-2, -0.1, 0.1, 3, 7)
get_closest_index(values, grid)
#> [1] 1 2 4 5 5 5
Created on 2020-05-29 by the reprex package (v0.3.0)
You can always implement custom binary search algorithm to find the closest value. Alternately, you can leverage standard implementation of libc bsearch(). You can use other binary search implementations as well, but it does not change the fact that you have to implement the comparing function carefully to find the closest element in array. The issue with standard binary search implementation is that it is meant for exact comparison. That means your improvised comparing function needs to do some kind of exactification to figure out if an element in array is close-enough. To achieve it, the comparing function needs to have awareness of other elements in the array, especially following aspects:
position of the current element (one which is being compared with the
key).
the distance with key and how it compares with neighbors (previous
or next element).
To provide this extra knowledge in comparing function, the key needs to be packaged with additional information (not just the key value). Once the comparing function have awareness on these aspects, it can figure out if the element itself is closest. When it knows that it is the closest, it returns "match".
The the following C code finds the closest value.
#include <stdio.h>
#include <stdlib.h>
struct key {
int key_val;
int *array_head;
int array_size;
};
int compar(const void *k, const void *e) {
struct key *key = (struct key*)k;
int *elem = (int*)e;
int *arr_first = key->array_head;
int *arr_last = key->array_head + key->array_size -1;
int kv = key->key_val;
int dist_left;
int dist_right;
if (kv == *elem) {
/* easy case: if both same, got to be closest */
return 0;
} else if (key->array_size == 1) {
/* easy case: only element got to be closest */
return 0;
} else if (elem == arr_first) {
/* element is the first in array */
if (kv < *elem) {
/* if keyval is less the first element then
* first elem is closest.
*/
return 0;
} else {
/* check distance between first and 2nd elem.
* if distance with first elem is smaller, it is closest.
*/
dist_left = kv - *elem;
dist_right = *(elem+1) - kv;
return (dist_left <= dist_right) ? 0:1;
}
} else if (elem == arr_last) {
/* element is the last in array */
if (kv > *elem) {
/* if keyval is larger than the last element then
* last elem is closest.
*/
return 0;
} else {
/* check distance between last and last-but-one.
* if distance with last elem is smaller, it is closest.
*/
dist_left = kv - *(elem-1);
dist_right = *elem - kv;
return (dist_right <= dist_left) ? 0:-1;
}
}
/* condition for remaining cases (other cases are handled already):
* - elem is neither first or last in the array
* - array has atleast three elements.
*/
if (kv < *elem) {
/* keyval is smaller than elem */
if (kv <= *(elem -1)) {
/* keyval is smaller than previous (of "elem") too.
* hence, elem cannot be closest.
*/
return -1;
} else {
/* check distance between elem and elem-prev.
* if distance with elem is smaller, it is closest.
*/
dist_left = kv - *(elem -1);
dist_right = *elem - kv;
return (dist_right <= dist_left) ? 0:-1;
}
}
/* remaining case: (keyval > *elem) */
if (kv >= *(elem+1)) {
/* keyval is larger than next (of "elem") too.
* hence, elem cannot be closest.
*/
return 1;
}
/* check distance between elem and elem-next.
* if distance with elem is smaller, it is closest.
*/
dist_right = *(elem+1) - kv;
dist_left = kv - *elem;
return (dist_left <= dist_right) ? 0:1;
}
int main(int argc, char **argv) {
int arr[] = {10, 20, 30, 40, 50, 60, 70};
int *found;
struct key k;
if (argc < 2) {
return 1;
}
k.key_val = atoi(argv[1]);
k.array_head = arr;
k.array_size = sizeof(arr)/sizeof(int);
found = (int*)bsearch(&k, arr, sizeof(arr)/sizeof(int), sizeof(int),
compar);
if(found) {
printf("found closest: %d\n", *found);
} else {
printf("closest not found. absurd! \n");
}
return 0;
}
Needless to say that bsearch() in above example should never fail (unless the array size is zero).
If you implement your own custom binary search, essentially you have to embed same comparing logic in the main body of binary search code (instead of having this logic in comparing function in above example).