Home About Contact
Go

Excel の countif 関数的なものをGolangで実装した

二つのリストがあり、 (1)両方のリストに含まれているもの、 (2)はじめのリストにだけ含まれているもの、 (3)あとのリストにだけ含まれているもの、それぞれを計算する必要が発生。 エクセルでそれを行うには countif を使う。

こんな風に:

Excel

これを Golang で実装した。(覚え書き)

package main

import (
	"fmt"
)

type Item struct {
	Count int
	Value string
}

func countif(list []string, a string) int {
	retVal := 0
	for _, item := range list {
		if item == a {
			retVal = retVal + 1
		}
	}
	return retVal
}

func filter(itemList []Item, accept func(int) bool) []Item {
	retVal := []Item{}
	for _, item := range itemList {
		if accept(item.Count) {
			retVal = append(retVal, item)
		}
	}
	return retVal
}

func collect(itemList []Item, f func(item Item) string) []string {
	retVal := []string{}
	for _, item := range itemList {
		retVal = append(retVal, f(item))
	}
	return retVal
}

func main() {
	listA := []string{"a", "b", "c", "d"}
	listB := []string{"b", "c", "d", "e", "f"}
	fmt.Println(fmt.Sprintf("listA : %v", listA))
	fmt.Println(fmt.Sprintf("listB : %v", listB))
	fmt.Println("")

	itemListA := []Item{}
	for _, value := range listA {
		item := Item{Count: countif(listB, value), Value: value}
		itemListA = append(itemListA, item)
	}

	itemListB := []Item{}
	for _, value := range listB {
		item := Item{Count: countif(listA, value), Value: value}
		itemListB = append(itemListB, item)
	}

	acceptIfCount0 := func(cnt int) bool { return (cnt == 0) }
	acceptIfCount1 := func(cnt int) bool { return (cnt == 1) }
	itemToValue := func(item Item) string { return item.Value }

	aAndBItemList := filter(itemListA, acceptIfCount1)
	aAndBValueList := collect(aAndBItemList, itemToValue)
	fmt.Println(fmt.Sprintf("A and B : %v", aAndBValueList))

	onlyAItemList := filter(itemListA, acceptIfCount0)
	onlyAValueList := collect(onlyAItemList, itemToValue)
	fmt.Println(fmt.Sprintf("only A : %v", onlyAValueList))

	onlyBItemList := filter(itemListB, acceptIfCount0)
	onlyBValueList := collect(onlyBItemList, itemToValue)
	fmt.Println(fmt.Sprintf("only B : %v", onlyBValueList))
}

実行する:

listA : [a b c d]
listB : [b c d e f]

A and B : [b c d]
only A : [a]
only B : [e f]

いっぽうのリストの要素を一つづつ取り出して、別のリストに何回出現するか調べる、すなわち countif する。 countif の結果が 1 のもののみにしたリストがすなわち両方に出現している要素を集めたリストになる。

片方のリストにしか出現しない要素のリストを計算するには、countif したときに 0 になるものを集める。