Grew up in Russia, lived in the States, moved to Germany, sometimes live in Spain. I program since I was 13. I used to program games, maps and now I reverse engineer password managers and other stuff
Location
Berlin and Málaga
Education
MS in CS from State Polytechnic University of St. Petersburg
And here's my take on it. You can sort by predicate. It's not exactly very efficient though, since the extension is recalculated every time. But come on, Go could be really annoying sometimes. Look at this verbosity:
Nah, no need for the boilerplate to define a custom sort. This would do sorting the map:
var m = make(map[string][]string)
for _, file := range dir {
if !file.IsDir() {
fileName := file.Name()
ext := strings.Split(fileName, ".")
switch {
case len(ext) > 1:
m[ext[len(ext)-1]] = append(m[ext[len(ext)-1]], fileName)
case len(ext) == 1:
m["no-ext"] = append(m["no-ext"], fileName)
}
}
}
for ext := range m { sort.Strings(m[ext]) }
Grew up in Russia, lived in the States, moved to Germany, sometimes live in Spain. I program since I was 13. I used to program games, maps and now I reverse engineer password managers and other stuff
Location
Berlin and Málaga
Education
MS in CS from State Polytechnic University of St. Petersburg
Yes, I have seen it. Your approach is different by just sorting a list of filenames. The orginal intent is to sort files by extension into different buckets.
Your use of filepath.Ext() is quit clever. Haven't thought of that.
var m = make(map[string][]string)
for _, file := range dir {
if !file.IsDir() {
fileName := file.Name()
ext := filepath.Ext(fileName)
m[ext] = append(m[ext], fileName)
}
}
for ext := range m { sort.Strings(m[ext]) }
You've come up with some great solutions in there, so I thought I'd share my own.
I restricted myself to fitting a subset of what you've solved thus far, that is to say, get all the files organised by category, and print them out as JSON. I've ignored plain / nested output, since that is somewhat trivial/not business logic.
Here's my solution:
packagemainimport("encoding/json""flag""io/ioutil""log""os""path/filepath""strings")vardirectorystringfuncmain(){flag.StringVar(&directory,"dir",".","sorter -dir ./path/to/dir")flag.Parse()files,err:=ioutil.ReadDir(directory)iferr!=nil{log.Fatal(err)}varcategories=make(map[string][]string)for_,file:=rangefiles{// skip directories.iffile.IsDir(){continue}ext:=filepath.Ext(file.Name())name:=strings.TrimSuffix(file.Name(),ext)// empty name signified a dotfile, skip that.ifname==""{continue}// get the absolute path to the file, or error outfpath,err:=filepath.Abs(filepath.Join(directory,file.Name()))iferr!=nil{log.Fatalf("failed building absolute path: %v",err)}// trim dots before adding to the map.ext=strings.TrimPrefix(ext,".")categories[ext]=append(categories[ext],fpath)}iferr:=json.NewEncoder(os.Stdout).Encode(categories);err!=nil{panic(err)}}
As you can see, I've drastically cut down on the number of operations needed to get there, as well as corrected for a few problems you weren't looking out for yet. These are mainly:
You should skip dotfiles or hidden files, which start with a . character (at least by default), as these are frequently config files or important somehow.
You're expending a lot of effort sorting / printing your data, when really all you need is a map to handle the listing
output from my program (against a sample directory):
I think the core of my issue is I'm also not leaning on the standard library as much as I should. I didn't realize filepath.Ext() was a thing. :/ Yeah, I read "sorting files by ext" as just that sorting alphabetically, had I left that out I would have been done quite a bit quicker. I suppose that made me go off the rails a bit so to speak. The different printing methods were not needed at all but what are you gonna do lol.
We're a place where coders share, stay up-to-date and grow their careers.
Steve, why do you sort inside the loop on every iteration?
And here's my take on it. You can sort by predicate. It's not exactly very efficient though, since the extension is recalculated every time. But come on, Go could be really annoying sometimes. Look at this verbosity:
In Ruby that would be:
Nah, no need for the boilerplate to define a custom sort. This would do sorting the map:
Edit: sorting the ˋ[]stringˋ within the ˋmap[string][]stringˋ. The map itself can't be sorted.
I don't have a map in my version. I sort an array by a predicate.
Yes, I have seen it. Your approach is different by just sorting a list of filenames. The orginal intent is to sort files by extension into different buckets.
Your use of filepath.Ext() is quit clever. Haven't thought of that.
This would make the example even shorter:
Hey Steve, fantastic start.
You've come up with some great solutions in there, so I thought I'd share my own.
I restricted myself to fitting a subset of what you've solved thus far, that is to say, get all the files organised by category, and print them out as JSON. I've ignored plain / nested output, since that is somewhat trivial/not business logic.
Here's my solution:
As you can see, I've drastically cut down on the number of operations needed to get there, as well as corrected for a few problems you weren't looking out for yet. These are mainly:
You should skip dotfiles or hidden files, which start with a
.character (at least by default), as these are frequently config files or important somehow.You're expending a lot of effort sorting / printing your data, when really all you need is a map to handle the listing
output from my program (against a sample directory):
usage:
sorter -dir ./sample | jqIf I wanted plain output, with a map I could do something like this:
which would output like so:
This is somewhat trite and gross but you get the point, dealing with one map makes this much easier to handle!
Looking forward to seeing what you come up with next!
I think the core of my issue is I'm also not leaning on the standard library as much as I should. I didn't realize
filepath.Ext()was a thing. :/ Yeah, I read "sorting files by ext" as just that sorting alphabetically, had I left that out I would have been done quite a bit quicker. I suppose that made me go off the rails a bit so to speak. The different printing methods were not needed at all but what are you gonna do lol.