按照字符串频率的映射对字符串切片进行排序

huangapple go评论80阅读模式
英文:

Sorting slices of strings by a map of their frequencies

问题

我有一个字符串切片的切片,并希望按照它们的频率进行排序。我尝试按照文档中的byAge示例(http://golang.org/pkg/sort/)的方法,但是不知道如何将频率列表传递给它。

意思是,示例的结果应该是:

[[a,b] [a,b,c,d] [a,c,d,e]]

是否可以通过使用自定义结构来表示"a",并将频率作为它自己的属性来实现?这似乎更符合byAge示例的方式。

func main() {

	transactions := [][]string{{"a", "b"}, {"b", "c", "d", "a"}, {"c", "d", "e", "a"}}

	frequencies := map[string]int{
		"a": 3,
		"b": 2,
		"c": 2,
		"d": 2,
		"e": 1,
	}

	fmt.Println(transactions, frequencies)

}
英文:

I have a slice of slices of strings, and want to sort them by their frequency, I tried to follow the byAge example from the docs here http://golang.org/pkg/sort/ but was unable how to pass a list of frequencies to it.

Meaning, the outcome of the example would be:

 [[a,b] [a,b,c,d] [a,c,d,e]]

Would the approach be to have "a" be represented by a custom struct with frequency as it's own attribute? That seems to be more in line with the byAge example.

func main() {

	transactions := [][]string{{"a", "b"}, {"b", "c", "d", "a"}, {"c", "d", "e", "a"}}

	frequencies := map[string]int{
		"a": 3,
		"b": 2,
		"c": 2,
		"d": 2,
		"e": 1,
	}
	
	fmt.Println(transactions, frequencies)
	
}

答案1

得分: 4

如果在排序过程中需要更多的数据,一种常见的方法是实现自己的结构体。在你的情况下,可以像这样实现一个结构体:

type SortableTransaction struct {
    data        []string
    frequencies map[string]int
}

data 是包含字符串的切片,frequencies 是特定频率表。

下面的实现可以用于 Sort 接口:

func (s SortableTransaction) Len() int { return len(s.data) }
func (s SortableTransaction) Less(i, j int) bool {
    return s.frequencies[s.data[i]] > s.frequencies[s.data[j]]
}
func (s SortableTransaction) Swap(i, j int) {
    s.data[j], s.data[i] = s.data[i], s.data[j]
}

如果你的频率表是常量的,当然可以在包级别声明它。

如果你想要对外部切片进行排序,你需要先对内部切片进行排序,然后再对外部切片进行排序。

英文:

In case you need more than the data you want to sort in the sorting process, a common way is
to implement your own struct, yes. In your case this would be something like this (on play):

type SortableTransaction struct {
	data        []string
	frequencies map[string]int
}

data would be the slice with strings and frequencies your specific frequency table.

The following implementation could be used for the Sort interface:

func (s SortableTransaction) Len() int { return len(s.data) }
func (s SortableTransaction) Less(i, j int) bool {
	return s.frequencies[s.data[i]] > s.frequencies[s.data[j]]
}
func (s SortableTransaction) Swap(i, j int) {
	s.data[j], s.data[i] = s.data[i], s.data[j]
}

If your frequency table is constant, you can declare it at package level of course.

In case you want to sort the outer slice as well, you'd have to sort the inner slices
first and then the outer slices.

答案2

得分: 1

例如,

package main

import (
	"fmt"
	"sort"
)

type NameFrequency struct {
	Name      string
	Frequency int
}

func (nf NameFrequency) String() string {
	return fmt.Sprintf("%s: %d", nf.Name, nf.Frequency)
}

type ByFrequency []NameFrequency

func (nf ByFrequency) Len() int      { return len(nf) }
func (nf ByFrequency) Swap(i, j int) { nf[i], nf[j] = nf[j], nf[i] }
func (nf ByFrequency) Less(i, j int) bool {
	less := nf[i].Frequency > nf[j].Frequency
	if nf[i].Frequency == nf[j].Frequency {
		less = nf[i].Name < nf[j].Name
	}
	return less
}

func SortByFrequency(names []string, frequencies map[string]int) []string {
	nf := make(ByFrequency, len(names))
	for i, name := range names {
		nf[i] = NameFrequency{name, frequencies[name]}
	}
	sort.Sort(ByFrequency(nf))
	sortedNames := make([]string, len(names))
	for i, nf := range nf {
		sortedNames[i] = nf.Name
	}
	return sortedNames
}

func main() {
	transactions := [][]string{{"a", "b"}, {"b", "c", "d", "a"}, {"c", "d", "e", "a"}}
	fmt.Println(transactions)
	frequencies := map[string]int{
		"a": 3,
		"b": 2,
		"c": 2,
		"d": 2,
		"e": 1,
	}
	fmt.Println(frequencies)
	sortedTransactions := make([][]string, len(transactions))
	for i, transaction := range transactions {
		sortedTransactions[i] = SortByFrequency(transaction, frequencies)
	}
	fmt.Println(sortedTransactions)
}

输出:

[[a b] [b c d a] [c d e a]]
map[a:3 b:2 c:2 d:2 e:1]
[[a b] [a b c d] [a c d e]]
英文:

For example,

package main

import (
	&quot;fmt&quot;
	&quot;sort&quot;
)

type NameFrequency struct {
	Name      string
	Frequency int
}

func (nf NameFrequency) String() string {
	return fmt.Sprintf(&quot;%s: %d&quot;, nf.Name, nf.Frequency)
}

type ByFrequency []NameFrequency

func (nf ByFrequency) Len() int      { return len(nf) }
func (nf ByFrequency) Swap(i, j int) { nf[i], nf[j] = nf[j], nf[i] }
func (nf ByFrequency) Less(i, j int) bool {
	less := nf[i].Frequency &gt; nf[j].Frequency
	if nf[i].Frequency == nf[j].Frequency {
		less = nf[i].Name &lt; nf[j].Name
	}
	return less
}

func SortByFrequency(names []string, frequencies map[string]int) []string {
	nf := make(ByFrequency, len(names))
	for i, name := range names {
		nf[i] = NameFrequency{name, frequencies[name]}
	}
	sort.Sort(ByFrequency(nf))
	sortedNames := make([]string, len(names))
	for i, nf := range nf {
		sortedNames[i] = nf.Name
	}
	return sortedNames
}

func main() {
	transactions := [][]string{{&quot;a&quot;, &quot;b&quot;}, {&quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;a&quot;}, {&quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;a&quot;}}
	fmt.Println(transactions)
	frequencies := map[string]int{
		&quot;a&quot;: 3,
		&quot;b&quot;: 2,
		&quot;c&quot;: 2,
		&quot;d&quot;: 2,
		&quot;e&quot;: 1,
	}
	fmt.Println(frequencies)
	sortedTransactions := make([][]string, len(transactions))
	for i, transaction := range transactions {
		sortedTransactions[i] = SortByFrequency(transaction, frequencies)
	}
	fmt.Println(sortedTransactions)
}

Output:

[[a b] [b c d a] [c d e a]]
map[a:3 b:2 c:2 d:2 e:1]
[[a b] [a b c d] [a c d e]]

huangapple
  • 本文由 发表于 2013年12月12日 08:39:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/20532869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定