《go语言程序设计》学习(六)

一,缩紧排序

package main

import (
    "fmt"
    "sort"
    "strings"
)

var original = []string{
    "Nonmentals",
    "    Hydrogen",
    "    Carbon",
    "    Nitrogenl",
    "    Oxygen",
    "Inner Transitionals",
    "    Lanthanides",
    "        Europium",
    "        Cerium",
    "    Actinides",
    "        Uranium",
    "        Plutonium",
    "        Curium",
    "Alkali Metals",
    "    Lithium",
    "    Sodium",
    "    Potassium",
}

func main() {
    fmt.Println("|        Original        |        Sorted        |")
    fmt.Println("|----------------------|-------------------|")
    sorted := SortedIndentedStrings(original)
    for i := range original {
        fmt.Printf("|%-19s|%-19s|\n", original[i], sorted[i])
    }
}
func SortedIndentedStrings(slice []string) []string {
    entries := populatedEntries(slice)
    return sortedEntries(entries)
}
func populatedEntries(slice []string) Entries {
    indent, IndentSize := computeIndent(slice)
    fmt.Printf("[%s] %d = %d\n", indent, len(indent), IndentSize)
    entries := make(Entries, 0)
    for _, item := range slice {
        i, level := 0, 0
        for strings.HasPrefix(item[i:], indent) {
            i += IndentSize
            level++
        }
        key := strings.ToLower(strings.TrimSpace(item))
        addEntry(level, key, item, &entries)
    }
    return entries
}
func computeIndent(slice []string) (string, int) {
    for _, item := range slice {
        if len(item) > 0 && (item[0] == ' ' || item[0] == '\t') {
            whitspace := rune(item[0])
            for i, char := range item[1:] {
                if char != whitspace {
                    i++
                    return strings.Repeat(string(whitspace), i), i
                }
            }
        }
    }
    return "", 0
}
func addEntry(level int, key, value string, entries *Entries) {
    if level == 0 {
        *entries = append(*entries, Entry{key, value, make(Entries, 0)})
    } else {
        addEntry(level-1, key, value,
            &((*entries)[entries.Len()-1].children))
    }
}
func sortedEntries(entries Entries) []string {
    var indentedSlice []string
    sort.Sort(entries)
    for _, entry := range entries {
        populatedIndentedStrings(entry, &indentedSlice)
    }
    return indentedSlice
}
func populatedIndentedStrings(entry Entry, indentedSlice *[]string) {
    *indentedSlice = append(*indentedSlice, entry.value)
    sort.Sort(entry.children)
    for _, child := range entry.children {
        populatedIndentedStrings(child, indentedSlice)
    }
}

type Entry struct {
    key      string
    value    string
    children Entries
}
type Entries []Entry

func (entries Entries) Len() int { return len(entries) }
func (entries Entries) Less(i, j int) bool {
    return entries[i].key < entries[j].key
}
func (entries Entries) Swap(i, j int) {
    entries[i], entries[j] = entries[j], entries[i]
}

这个代码,还是很简单,不过还不算很完美,因为有一个假定的前提——所有文本行都使用相同的缩紧。

代码逻辑:

首先遍历所有行数据,直到找到一行,是用空格活着tab开头的文字,并获取这行有多少个该字符,以此作为判定缩紧等级的基础。

然后再次便利所有行数据,用string.hasPrefix获取反复对字符串“开头”进行计算,计算结果即缩紧等级。

使用缩紧等级构造数据结构Entry,缩紧为0,则新增根Entrie,缩紧为1,则在根Entry的child上,构建改Entry,为2,则在Entry的child的child上构建。

最后使用定义的Less方法做字符串的比较,对每个根的每一层Entry分别进行sort。

使用的数据结构,如果假设有一个叫root的Entry节点,就可以认为是一棵树啦。

 

posted @ 2015-08-04 22:03  诡城  阅读(271)  评论(0编辑  收藏  举报