Skip to content

Instantly share code, notes, and snippets.

@ernado
Created June 7, 2019 12:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ernado/9d6bb51ab91887cc02a9540df4fb535d to your computer and use it in GitHub Desktop.
Save ernado/9d6bb51ab91887cc02a9540df4fb535d to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
"time"
j "github.com/json-iterator/go"
)
type Debtor struct {
Companies []string
Phones []string
Debt int64
}
var fileName = flag.String("f", "1.json", "file name to open")
func main() {
flag.Parse()
t := time.Now()
f, err := os.Open(*fileName)
if err != nil {
log.Fatalln("failed to open file:", err)
}
defer f.Close()
cfg := j.ConfigDefault
iter := j.Parse(cfg, f, 5*1024)
debtors := make([]Debtor, 0, 100)
debtorByPhone := make(map[string]int, 100)
iter.ReadArrayCB(func(i *j.Iterator) bool {
var (
company string
debt int64
)
phones := make([]string, 0, 10)
read := i.ReadMapCB(func(i *j.Iterator, k string) bool {
switch k {
case "company":
switch i.WhatIsNext() {
case j.StringValue:
company = i.ReadString()
case j.ObjectValue:
i.ReadMapCB(func(i *j.Iterator, s string) bool {
company = i.ReadString()
return true
})
default:
i.Skip()
}
case "debt":
switch i.WhatIsNext() {
case j.NumberValue:
debt = i.ReadInt64()
case j.StringValue:
v := i.ReadString()
n, err := strconv.ParseInt(v, 10, 64)
if err != nil {
panic(err)
}
debt = n
default:
i.Skip()
}
case "phones", "phone":
switch i.WhatIsNext() {
case j.StringValue:
phones = append(phones, i.ReadString())
case j.NumberValue:
phones = append(phones, i.ReadNumber().String())
case j.ArrayValue:
i.ReadArrayCB(func(i *j.Iterator) bool {
switch i.WhatIsNext() {
case j.StringValue:
phones = append(phones, i.ReadString())
case j.NumberValue:
phones = append(phones, i.ReadNumber().String())
default:
i.Skip()
}
return true
})
default:
i.Skip()
}
default:
i.Skip()
}
return true
})
var (
id int
found bool
)
for _, p := range phones {
id, found = debtorByPhone[p]
if found {
break
}
}
if !found {
// Creating new company.
debtors = append(debtors, Debtor{
Companies: []string{company},
Phones: phones,
})
id = len(debtors) - 1
for _, p := range phones {
debtorByPhone[p] = id
}
}
nameFound := false
for _, name := range debtors[id].Companies {
if name == company {
nameFound = true
break
}
}
if !nameFound {
debtors[id].Companies = append(debtors[id].Companies, company)
}
for _, p := range phones {
found := false
for _, pp := range debtors[id].Phones {
if pp == p {
found = true
break
}
}
if !found {
debtorByPhone[p] = id
debtors[id].Phones = append(debtors[id].Phones, p)
}
}
debtors[id].Debt += debt
return read
})
fmt.Println("total debtors:", len(debtors))
fmt.Println("total time:", time.Since(t))
for _, d := range debtors {
sort.Strings(d.Companies)
sort.Strings(d.Phones)
fmt.Printf("%s:\n", strings.Join(d.Companies, ", "))
fmt.Printf("\t%s\n", strings.Join(d.Phones, ", "))
fmt.Printf("\t%d\n", d.Debt)
}
}
@ernado
Copy link
Author

ernado commented Jun 7, 2019

Go: (544ms):

total debtors: 2
total time: 544.972375ms
Первая коллекторская, Рога и копыта, Шестерочка:
        123, 2128506, 234, 456, 788, 789
        910000000
Казачий спас, Святой престол:
        234567, 345678, 666
        433200000

Rust (917ms) https://gist.github.com/red75prime/53111e066cb1a32721c461b24eadbe6e

PROCESSED: 1000000 objects in 917.121288ms, 0 errors found
-------------------------------
#0: debt: 910000000
companies: {"Рога и копыта", "Первая коллекторская", "Шестерочка"}
phones: {"789", "788", "123", "234", "2128506", "456"}
-------------------------------
#1: debt: 433200000
companies: {"Казачий спас", "Святой престол"}
phones: {"345678", "666", "234567"}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment