2

I have a list of paths

[]string{"/a/path/to/something", "/a/path/in/something", "/a/path/in/something/else"}

I'd like to remove the Longest Common prefix from all paths so that the remaining part of it is the distinct part of the path.

For the above example the result should be

[]string{"to/something", "in/something", "in/something/else"}

My attempt so far has been fairly brute force so far:

  1. Split up all paths by "/"

    map["/a/path/to/something": [a path to something], "": [a path in something], "/a/path/in/something/else": [a path in something else]}

  2. Pick any entry of the map and use that as a reference

  3. Iterate over the single elements of that picked entry and check the others on that position if they match
  4. If a non matching element is found the sequence is broken; take the remaining path of each path from path[len(iterated_elem_so_far):]

Is there a more sophisticated way of accomplishing this?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
wasp256
  • 5,943
  • 12
  • 72
  • 119

1 Answers1

2

What you're doing should work. I don't understand the part about the map though, so here's an algorithm that first finds the longest prefix, and then removes that from all the paths:

func removeLargestPrefix(in []string) []string {
   // Store split paths in results
   results:=make([][]string,0,len(in))
   // Pick the first path as the longest prefix
   results=append(results,strings.Split(in[0],"/"))
   longest:=results[0]
   // cmp shortents the known longest prefix
   cmp:=func(a []string)  {
       if len(a)<len(longest) {
         longest=longest[:len(a)]
       }
       for i:=0;i<len(longest);i++ {
          if a[i]!=longest[i] {
             longest=longest[:i]
             return
          }
       }
   }
   // process all paths
   for i:=1;i<len(in);i++ {
       r:=strings.Split(in[i],"/")
       results=append(results,r)
       cmp(r)
   }
   // here, len(longest) is the length of the longest prefix
   out:=make([]string,0,len(results))
   for _,r:=range results {
      out=append(out,strings.Join(r[len(longest):],"/"))
   }
   return out
}

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • Code is correct. I just had a small remark. You didn’t really need to define the `cmp` function. You could have replaced the call to `cmp(r)` with the body of the `cmp` function – chmike Jan 06 '20 at 08:20
  • Yeah that's roughly what I came up with as well; the thing that bothered me was the amount of for loops required but there doesn't seem a way around that... – wasp256 Jan 07 '20 at 01:04