Change Merger implementation on --no-sort

This commit is contained in:
Junegunn Choi 2015-01-10 14:24:12 +09:00
parent 2d9b38b93e
commit 6e86fee588
2 changed files with 29 additions and 27 deletions

View File

@ -1,12 +1,15 @@
package fzf package fzf
import "fmt"
var EmptyMerger *Merger = NewMerger([][]*Item{}, false) var EmptyMerger *Merger = NewMerger([][]*Item{}, false)
type Merger struct { type Merger struct {
lists [][]*Item lists [][]*Item
merged []*Item merged []*Item
cursors []int cursors []int
done bool sorted bool
count int
} }
func NewMerger(lists [][]*Item, sorted bool) *Merger { func NewMerger(lists [][]*Item, sorted bool) *Merger {
@ -14,41 +17,37 @@ func NewMerger(lists [][]*Item, sorted bool) *Merger {
lists: lists, lists: lists,
merged: []*Item{}, merged: []*Item{},
cursors: make([]int, len(lists)), cursors: make([]int, len(lists)),
done: false} sorted: sorted,
if !sorted { count: 0}
for _, list := range lists {
mg.merged = append(mg.merged, list...) for _, list := range mg.lists {
} mg.count += len(list)
mg.done = true
} }
return &mg return &mg
} }
func (mg *Merger) Length() int { func (mg *Merger) Length() int {
cnt := 0 return mg.count
for _, list := range mg.lists {
cnt += len(list)
}
return cnt
} }
func (mg *Merger) Get(idx int) *Item { func (mg *Merger) Get(idx int) *Item {
if mg.done { if len(mg.lists) == 1 {
return mg.merged[idx]
} else if len(mg.lists) == 1 {
return mg.lists[0][idx] return mg.lists[0][idx]
} else if !mg.sorted {
for _, list := range mg.lists {
numItems := len(list)
if idx < numItems {
return list[idx]
}
idx -= numItems
}
panic(fmt.Sprintf("Index out of bounds (unsorted, %d/%d)", idx, mg.count))
} }
mg.buildUpto(idx) return mg.mergedGet(idx)
return mg.merged[idx]
} }
func (mg *Merger) buildUpto(upto int) { func (mg *Merger) mergedGet(idx int) *Item {
numBuilt := len(mg.merged) for i := len(mg.merged); i <= idx; i++ {
if numBuilt > upto {
return
}
for i := numBuilt; i <= upto; i++ {
minRank := Rank{0, 0, 0} minRank := Rank{0, 0, 0}
minIdx := -1 minIdx := -1
for listIdx, list := range mg.lists { for listIdx, list := range mg.lists {
@ -72,8 +71,8 @@ func (mg *Merger) buildUpto(upto int) {
mg.merged = append(mg.merged, chosen[mg.cursors[minIdx]]) mg.merged = append(mg.merged, chosen[mg.cursors[minIdx]])
mg.cursors[minIdx] += 1 mg.cursors[minIdx] += 1
} else { } else {
mg.done = true panic(fmt.Sprintf("Index out of bounds (sorted, %d/%d)", i, mg.count))
return
} }
} }
return mg.merged[idx]
} }

View File

@ -19,6 +19,9 @@ func randItem() *Item {
func TestEmptyMerger(t *testing.T) { func TestEmptyMerger(t *testing.T) {
assert(t, EmptyMerger.Length() == 0, "Not empty") assert(t, EmptyMerger.Length() == 0, "Not empty")
assert(t, EmptyMerger.count == 0, "Invalid count")
assert(t, len(EmptyMerger.lists) == 0, "Invalid lists")
assert(t, len(EmptyMerger.merged) == 0, "Invalid merged list")
} }
func buildLists(partiallySorted bool) ([][]*Item, []*Item) { func buildLists(partiallySorted bool) ([][]*Item, []*Item) {
@ -72,7 +75,7 @@ func TestMergerSorted(t *testing.T) {
// Inverse order // Inverse order
mg2 := NewMerger(lists, true) mg2 := NewMerger(lists, true)
for i := cnt - 1; i >= cnt; i-- { for i := cnt - 1; i >= 0; i-- {
if items[i] != mg2.Get(i) { if items[i] != mg2.Get(i) {
t.Error("Not sorted", items[i], mg2.Get(i)) t.Error("Not sorted", items[i], mg2.Get(i))
} }