引き続き第2章も解いていきます。
第2章はUnixコマンドの基礎ということで、以下のテキストファイルを読み込んで処理を行う内容と
なっています。
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
###10. 行数のカウント
行数をカウントせよ。確認にはwcコマンドを用いよ。
→1行ずつ読み込んだらスライスに入れて、要素数をカウントすればいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
open := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
file := open("../data/hightemp.txt")
fmt.Println(len(file))
}
参考:Go でファイルや標準入力からテキストを一行ずつ読む
http://www.yunabe.jp/tips/golang_readlines.html
###11. タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ。
→読み込んだのを1行ずつ、strings.Replaceでスペースに置換すればおk
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
open := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
for _, v := range open("../data/hightemp.txt") {
fmt.Println(strings.Replace(v, "\t", " ", -1))
}
}
###12. 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ。
→1行ずつ読むときにタブでスプリットする。配列の0番目と1番目がそれぞれ1列目と2列目になるのでそれをファイルに書き込めばいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
arr1, arr2 := []string{}, []string{}
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
for _, v := range read("../data/hightemp.txt") {
tmp := strings.Fields(v)
arr1 = append(arr1, tmp[0])
arr2 = append(arr2, tmp[1])
}
write := func(text string, data []string) {
f, err := os.Create(text)
if err != nil {
panic(err)
}
w := bufio.NewWriter(f)
for _, v := range data {
fmt.Fprint(w, v, "\n")
}
w.Flush()
}
write("col1.txt", arr1)
write("col2.txt", arr2)
}
###13. col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ。確認にはpasteコマンドを用いよ。
→col1.txt、col2.txtをそれぞれ読み取って、2個のスライスを引数にファイルに書けばいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
arr1, arr2 := []string{}, []string{}
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
arr1 = read("col1.txt")
arr2 = read("col2.txt")
write := func(row1, row2 []string, text string) {
f, err := os.Create(text)
if err != nil {
panic(err)
}
w := bufio.NewWriter(f)
for i, _ := range row1 {
fmt.Fprint(w, row1[i], "\t", row2[i], "\n")
}
w.Flush()
}
write(arr1, arr2, "merge.txt")
}
###14. 先頭からN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ。
→N行分までFor文で出力さすればいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
text := read("../data/hightemp.txt")
n, _ := strconv.Atoi(os.Args[1])
for i := 0; i < n; i++ {
fmt.Println(text[i])
}
}
###15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ。
→末尾だからN行目以降、NからFor文回せばいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
text := read("../data/hightemp.txt")
n, _ := strconv.Atoi(os.Args[1])
for i := len(text) - n; i < len(text); i++ {
fmt.Println(text[i])
}
}
###16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ。
→行数 / N の値で割り切れたときにファイルに書けばいいんじゃね。
24行を4分割すると、24 / 4 = 6 だから、For文回したときに6で割り切れた時にファイルに書けば
6行ずつファイルに4分割されんじゃね?
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
write := func(row []string, text string) {
f, err := os.Create(text)
if err != nil {
panic(err)
}
w := bufio.NewWriter(f)
for _, v := range row {
fmt.Fprint(w, v, "\n")
}
w.Flush()
}
text := read("../data/hightemp.txt")
n, _ := strconv.Atoi(os.Args[1])
splitcnt := len(text) / n
tmp := []string{}
for i := 1; i <= len(text); i++ {
tmp = append(tmp, text[i-1])
if i%splitcnt == 0 {
write(tmp, strconv.Itoa(i)+".txt")
tmp = []string{}
}
}
}
###17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ。
→mapにkeyに1列目を入れてって集合を出せばいいんじゃね
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
makemap := func(arr []string) map[string]bool {
tmp := make(map[string]bool)
for _, v := range arr {
_, ok := tmp[v]
if ok == false {
tmp[v] = true
}
}
return tmp
}
txt := read("../data/hightemp.txt")
var row1 = []string{}
for _, v := range txt {
tmp := strings.Fields(v)
row1 = append(row1, tmp[0])
}
for i, _ := range makemap(row1) {
fmt.Println(i)
}
}
###18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ)。確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい)。
→1列目~4列目をひとまず構造体にセットして、3列目の温度でソートさせるインターフェイスを↓の記事見ながら実装するべさ
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
type Hightemp struct {
pref string
town string
temp float64
date string
}
type ByTemp []Hightemp
func (a ByTemp) Len() int {
return len(a)
}
func (a ByTemp) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a ByTemp) Less(i, j int) bool {
return a[i].temp < a[j].temp
}
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
txt := read("../data/hightemp.txt")
arr := []Hightemp{}
for _, v := range txt {
tmp := strings.Fields(v)
ondo, _ := strconv.ParseFloat(tmp[2], 64)
tmp1 := Hightemp{tmp[0], tmp[1], ondo, tmp[3]}
arr = append(arr, tmp1)
}
sort.Sort(ByTemp(arr))
for _, v := range arr {
fmt.Printf("%v\t%v\t%v\t%v\n", v.pref, v.town, v.temp, v.date)
}
}
###19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ。確認にはcut, uniq, sortコマンドを用いよ。
→1列目の文字列とカウント回数のmapを作成して構造体にいれてソートさせればいいんじゃね?
18と同じようなことを出現回数でやればよくね。
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
type Hightemp struct {
pref string
cnt int
}
type ByCnt []Hightemp
func (a ByCnt) Len() int {
return len(a)
}
func (a ByCnt) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a ByCnt) Less(i, j int) bool {
return a[i].cnt > a[j].cnt
}
func main() {
read := func(path string) []string {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
}
defer f.Close()
lines := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if serr := scanner.Err(); serr != nil {
fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
}
return lines
}
makemap := func(arr []string) map[string]int {
tmp := make(map[string]int)
for _, v := range arr {
_, ok := tmp[v]
if ok == false {
tmp[v] = 1
} else {
tmp[v] = tmp[v] + 1
}
}
return tmp
}
txt := read("../data/hightemp.txt")
var row1 = []string{}
for _, v := range txt {
tmp := strings.Fields(v)
row1 = append(row1, tmp[0])
}
arr := []Hightemp{}
for i, v := range makemap(row1) {
tmp := Hightemp{i, v}
arr = append(arr, tmp)
}
sort.Sort(ByCnt(arr))
for _, v := range arr {
fmt.Printf("%v %v\n", v.pref, v.cnt)
}
}