Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fuzzy finder as a Go library

ktr
May 18, 2019

Fuzzy finder as a Go library

Go Conference 2019 Spring

ktr

May 18, 2019
Tweet

More Decks by ktr

Other Decks in Programming

Transcript

  1. BU(P$POGFSFODF4QSJOH
    Fuzzy finder as a

    Go library

    View full-size slide

  2. XIPBNJ
    w LUS Ωλϩʔɺ!LUS@

    w ৽ଔ
    w (Pͱ$-*πʔϧ͕͖͢

    View full-size slide

  3. 'V[[ZpOEFSJTԿ

    View full-size slide

  4. wೖྗʹର͠ɺ͍͋·͍ݕࡧ

    ʹΑͬͯΠϯλϥΫςΟϒʹ

    ಛఆͷߦΛબ୒Ͱ͖Δ
    wίϚϯυϥΠϯGV[[ZpOEFS

    G[G G[Z FUD

    'V[[ZpOEFS

    View full-size slide

  5. $ cd `ghq root`/`ghq list | fzf`
    HIR഑ԼͷϦϙδτϦʹҠಈ

    View full-size slide

  6. $ git branch | egrep -v '^\*' | fzf | 

    xargs git checkout
    ΠϯλϥΫςΟϒʹνΣοΫΞ΢τઌ

    ϒϥϯνΛબ୒

    View full-size slide

  7. ίϚϯυϥΠϯGV[[ZpOEFSΛ

    ѻ͏ࡍʹൃੜ͢Δ໰୊

    View full-size slide

  8. w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ
    w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞
    ίϚϯυϥΠϯGV[[ZpOEFS

    Λѻ͏ࡍʹൃੜ͢Δ໰୊

    View full-size slide

  9. w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ
    w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞
    ίϚϯυϥΠϯGV[[ZpOEFS

    Λѻ͏ࡍʹൃੜ͢Δ໰୊

    View full-size slide

  10. w શ͘ಉ͡಺༰Λද͍ࣔͯ͠Δߦ͕ෳ਺͋Δͱ͖ɺ

    ϓϩάϥϜతɺϢʔβతʹ΋ͦΕΒΛ۠ผͰ͖ͳ͍
    w ৘ใྔΛ૿΍͢͜ͱͰϢχʔΫʹ͸Ͱ͖Δ͕ʜ
    w ͱʹ͔͘ݟͮΒ͍
    w ิॿతͳ৘ใ΋ݕࡧର৅ʹͳΓɺݕࡧਫ਼౓͕௿Լ͢Δ
    ߦࢦ޲ͷݶք

    View full-size slide

  11. w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ
    w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞
    ίϚϯυϥΠϯGV[[ZpOEFS

    Λѻ͏ࡍʹൃੜ͢Δ໰୊

    View full-size slide

  12. w DEίϚϯυͷ֦ு
    w ύεͷཤྺΛΠϯλϥΫςΟϒʹબ୒ͯ͠Ҡಈ
    CCSFOIBODE

    View full-size slide

  13. w J5VOFTΛίϚϯυϥΠϯ͔Βૢ࡞Ͱ͖Δ
    w J5VOFTͷۂΛΠϯλϥΫςΟϒʹબ୒ɺ࠶ੜ
    LUSJUVOFTDMJ

    View full-size slide

  14. w ίϚϯυϥΠϯGV[[ZpOEFSͷΠϯετʔϧ
    w πʔϧʹೝࣝͤ͞ΔͨΊͷઃఆ
    w ؀ڥม਺ͳͲ
    πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞

    View full-size slide

  15. 'V[[ZpOEFSΛϥΠϒϥϦ

    ͱͯ͠ఏڙ͢Δ

    View full-size slide

  16. w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ
    ‣ ಺෦తʹঢ়ଶΛ࣋ͭ͜ͱ͕Ͱ͖ɺϓϩάϥϜଆͰॏෳߦ
    Λ۠ผͰ͖Δ
    w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞
    ‣ (PʹͷΈґଘ͢ΔͨΊɺͦ΋ͦ΋πʔϧͷઃఆ͕ෆཁ
    'V[[ZpOEFSBTBMJCSBSZ

    View full-size slide

  17. LUSHPGV[[ZpOEFS

    View full-size slide

  18. func Find(
    slice interface{},
    itemFunc func(i int) string,
    opts ...Option,
    ) (idx int, err error)
    LUSHPGV[[ZpOEFS

    View full-size slide

  19. EFNP
    ίϚϯυϥΠϯGV[[ZpOEFS

    View full-size slide

  20. func main() {
    var slice []string
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
    slice = append(slice, s.Text())
    }
    idx, err := fuzzyfinder.Find(slice, func(i int) string {
    return slice[i]
    })
    if err != nil {
    fmt.Fprintf(os.Stderr, "failed to find: %s\n", err)
    os.Exit(1)
    }
    fmt.Println(slice[idx])
    }

    View full-size slide

  21. $ (cd $GOPATH/src/github.com/golang/go; git ls-files) | ./cli

    View full-size slide

  22. EFNP
    ಉҰ಺༰ͷߦͷදࣔ

    View full-size slide

  23. w ϓϩάϥϜࣗ਎͸ॏෳߦͷ൑ผ͕Ͱ͖Δ͕ɺ

    Ϣʔβ͸౰વ൑ผͰ͖ͳ͍
    w ิॿతͳ৘ใΛϓϨϏϡʔ΢Πϯυ΢Ͱදࣔ
    ಉҰ಺༰ͷߦͷදࣔ

    View full-size slide

  24. func main() {
    idx, err := fuzzyfinder.FindMulti(songs, func(i int) string {
    return songs[i].Title
    }, fuzzyfinder.WithPreviewWindow(func(i, w, h int) string {
    if i == -1 {
    return ""
    }
    return fmt.Sprintf(
    "Title: %s\nArtist: %s\nAlbum: %s\n",
    songs[i].Title, songs[i].ArtistName, songs[i].AlbumName)
    }))
    if err != nil {
    fmt.Fprintf(os.Stderr, "failed to find: %s\n", err)
    os.Exit(1)
    }
    for _, i := range idx {
    fmt.Println(fmt.Sprintf(
    "%s / %s / %s",
    songs[i].Title, songs[i].ArtistName, songs[i].AlbumName))
    }
    }

    View full-size slide

  25. HPGV[[ZpOEFSͷ࣮૷

    View full-size slide

  26. w ೖྗͱީิߦͷϚονϯά
    w Ϛονͨ͠ߦͷείΞϦϯά
    'V[[ZpOEFSΛߏ੒͢Δཁૉ

    View full-size slide

  27. w ೖྗlHSQDzΛؚΉߦΛ୳͢
    w ۪௚ʹೋॏϧʔϓճ͚ͩ͢
    Ϛονϯά

    View full-size slide

  28. w ظ଴͍ͯ͠ΔߦΛ༏ઌతʹදࣔ͢ΔͨΊʹඞཁ
    w ֤ߦΛιʔτ͢ΔͨΊͷείΞΛࢉग़͢Δ
    είΞϦϯά

    View full-size slide

  29. w ϨʔϕϯγϡλΠϯڑ཭
    w /FFEMFNBO8VOTDI
    w 4NJUI8BUFSNBO
    ৭ʑͳείΞϦϯάΞϧΰϦζϜ

    View full-size slide

  30. w ϨʔϕϯγϡλΠϯڑ཭εϖϧνΣοΧʔ
    w /FFEMFNBO8VOTDIG[Z
    w 4NJUI8BUFSNBOG[G
    ৭ʑͳείΞϦϯάΞϧΰϦζϜ

    View full-size slide

  31. w ϨʔϕϯγϡλΠϯڑ཭
    w /FFEMFNBO8VOTDI
    w 4NJUI8BUFSNBO
    ৭ʑͳείΞϦϯάΞϧΰϦζϜ

    View full-size slide

  32. w άϩʔόϧ
    ΞϥΠϯϝϯτΞϧΰϦζϜͷҰͭ
    w ͋ΔͭͷจࣈྻΛ੔ྻͤ͞ΔͨΊʹ

    ඞཁͳίετΛಈతܭը๏Λ࢖ͬͯٻΊΔ
    /FFEMFNBO8VOTDIΞϧΰϦζϜ

    View full-size slide

  33. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    | A T A C
    -------------------------
    |
    A|
    C|

    View full-size slide

  34. w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒
    w ۭന Ϊϟοϓ
    ΛࠨͷจࣈྻʹҰͭૠೖ
    w ۭന Ϊϟοϓ
    Λ্ͷจࣈྻʹҰͭૠೖ
    w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον

    /FFEMFNBO8VOTDIΞϧΰϦζϜ

    View full-size slide

  35. w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒
    w ۭന Ϊϟοϓ
    ΛࠨͷจࣈྻʹҰͭૠೖ
    w ۭന Ϊϟοϓ
    Λ্ͷจࣈྻʹҰͭૠೖ
    w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον
    PS
    /FFEMFNBO8VOTDIΞϧΰϦζϜ

    View full-size slide

  36. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    ยํ͕ۭจࣈͷͱ͖ͷ

    είΞ͸࠷ॳʹٻ·Δ
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2
    C| -4

    View full-size slide

  37. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    e.g.


    “ATAC” ʹରͯ͠ “” ΛΞϥ
    Πϯϝϯτ͢Δʹ͸ 4 ͭ
    ΪϟοϓΛૠೖ͢Ε͹ྑ͍
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2
    C| -4

    View full-size slide

  38. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    “” ͱ “” ʹͦΕͧΕ
    จࣈΛରԠ෇͚Δ৔߹ɺ
    Ϛον͍ͯ͠ΔͷͰ +2

    (0 + 2 = 2)
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2
    C| -4

    View full-size slide

  39. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    “A” ͱ “” ͕͋Γɺ

    ޙऀʹΪϟοϓΛૠೖ

    ͢ΔͷͰ -2
    (-2 - 2 = -4)
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2
    C| -4

    View full-size slide

  40. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    “” ͱ “A” ͕͋Γɺ

    લऀʹΪϟοϓΛૠೖ

    ͢ΔͷͰ -2

    (-2 - 2 = -4)
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2
    C| -4

    View full-size slide

  41. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    match = 2
    left gap = -4
    top gap = -4


    Ͳ͔͜ΒٻΊ͔ͨΛه࿥
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2
    C| -4

    View full-size slide

  42. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    mismatch = -3
    left gap = 0
    top gap = -6
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0
    C| -4

    View full-size slide

  43. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    match = -2
    left gap = -2
    top gap = -8
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0 -2
    C| -4

    View full-size slide

  44. /FFEMFNBO8VOTDIΞϧΰϦζϜ
    mismatch = -7
    left gap = -4
    top gap = -10
    | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0 -2 -4
    C| -4

    View full-size slide

  45. | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0 -2 -4
    C| -4 0 1 -1 0
    /FFEMFNBO8VOTDIΞϧΰϦζϜ
    ࠷ऴతͳঢ়ଶ

    View full-size slide

  46. | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0 -2 -4
    C| -4 0 1 -1 0
    /FFEMFNBO8VOTDIΞϧΰϦζϜ
    ຤ඌͷείΞ͕

    ͜ͷจࣈྻؒͷείΞ

    είΞ = 0

    View full-size slide

  47. | A T A C
    -------------------------
    | 0 -2 -4 -6 -8
    A| -2 2 0 -2 -4
    C| -4 0 1 -1 0
    /FFEMFNBO8VOTDIΞϧΰϦζϜ
    A T A C
    | |
    A - - C
    ຤ඌ͔Β໼ҹͷॱʹḷΔ

    View full-size slide

  48. w ϨʔϕϯγϡλΠϯڑ཭
    w /FFEMFNBO8VOTDI
    w 4NJUI8BUFSNBO
    ৭ʑͳείΞϦϯάΞϧΰϦζϜ

    View full-size slide

  49. w ϩʔΧϧΞϥΠϯϝϯτΞϧΰϦζϜͷҰͭ
    w શମతʹ͸ࣅ͍ͯͳ͍ͭͷจࣈྻͷ

    ہॴతͳΞϥΠϯϝϯτΛٻΊΔΞϧΰϦζϜ
    w /FFEMFNBO8VTDIͱඇৗʹࣅ͍ͯΔ͕ɺ

    είΞ͕ϚΠφεʹͳΒͳ͍
    4NJUI8BUFSNBOΞϧΰϦζϜ

    View full-size slide

  50. 4NJUI8BUFSNBOΞϧΰϦζϜ
    w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒
    w ۭന Ϊϟοϓ
    ΛࠨͷจࣈྻʹҰͭૠೖ
    w ۭന Ϊϟοϓ
    Λ্ͷจࣈྻʹҰͭૠೖ
    w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον

    w θϩ஋

    View full-size slide

  51. | A T A C
    -------------------------
    | 0 0 0 0 0
    A| 0 2 0 2 0
    C| 0 0 1 0 4
    4NJUI8BUFSNBOΞϧΰϦζϜ
    ຤ඌ͔Βઌ಄Ͱ͸ͳ͘ɺ
    ෦෼తͳΞϥΠϯϝϯτ
    (຤ඌ͔Β 0 ·Ͱ)

    View full-size slide

  52. | A T A C
    -------------------------
    | 0 0 0 0 0
    A| 0 2 0 2 0
    C| 0 0 1 0 4
    4NJUI8BUFSNBOΞϧΰϦζϜ
    είΞ = 4

    View full-size slide

  53. | A T A C
    -------------------------
    | 0 0 0 0 0
    A| 0 2 0 2 0
    C| 0 0 1 0 4
    4NJUI8BUFSNBOΞϧΰϦζϜ
    A T A C
    | |
    - - A C

    View full-size slide

  54. w ΪϟοϓΛ࡞Δ͜ͱࣗମ΁ͷϖφϧςΟ
    w ઌ಄ҰகϘʔφε
    w FUD
    ϘʔφεͱϖφϧςΟ

    View full-size slide

  55. w ઃܭ͸ͦΕͧΕͷ࣮૷ʹΑΔ
    w G[ZKIBXUIPSOG[Z"-(03*5).NE
    w G[GKVOFHVOOG[GTSDBMHPBMHPHP
    ϘʔφεͱϖφϧςΟ

    View full-size slide

  56. ೖྗʹϚον͢ΔߦΛߜΓࠐΉ
    4NJUI8BUFSNBOͰ֤ߦΛείΞϦϯά
    είΞ͕ߴ͍΋ͷ͔Βॱʹදࣔ
    HPGV[[ZpOEFSͷ࣮૷

    View full-size slide

  57. w ॏෳߦͷ۠ผ
    w ϓϨϏϡʔ΢Πϯυ΢Ͱͷิॿతͳ৘ใͷ෇༩
    w πʔϧ͔ΒGV[[ZpOEFSΛͭ͘Δࡍʹɺ

    ίϚϯυϥΠϯGV[[ZpOEFS΁ͷґଘΛղফͰ
    ͖Δ
    HPGV[[ZpOEFSͷղܾ͢Δ͜ͱ

    View full-size slide

  58. 5IBOLTGPSMJTUFOJOH

    View full-size slide