Find common directory path: Difference between revisions
(→{{header|Tcl}}: Corrected to allow arbitrary separators) |
|||
Line 50: | Line 50: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
<lang tcl> |
<lang tcl>package require Tcl 8.5 |
||
proc pop {varname} { |
|||
upvar 1 $varname var |
|||
set |
set var [lassign $var head] |
||
return $head |
return $head |
||
} |
} |
||
proc common_prefix {dirs} { |
proc common_prefix {dirs {separator "/"}} { |
||
set parts [ |
set parts [split [pop dirs] $separator] |
||
while {[llength $dirs]} { |
while {[llength $dirs]} { |
||
set r {} |
set r {} |
||
foreach cmp $parts elt [ |
foreach cmp $parts elt [split [pop dirs] $separator] { |
||
if {$cmp ne $elt} break |
if {$cmp ne $elt} break |
||
lappend r $cmp |
lappend r $cmp |
||
Line 67: | Line 67: | ||
set parts $r |
set parts $r |
||
} |
} |
||
return [ |
return [join $parts $separator] |
||
}</lang> |
}</lang> |
||
Revision as of 09:11, 24 March 2010
You are encouraged to solve this task according to the task description, using any language you may know.
Given a set of strings representing directory paths and a single character directory separator; return a string representing that part of the directory tree that is common to all the directories.
Test your routine using the forward slash '/' character as the directory separator and the following three strings as input paths:
'/home/user1/tmp/coverage/test' '/home/user1/tmp/covert/operator' '/home/user1/tmp/coven/members'
Note: The resultant path should be the valid directory '/home/user1/tmp'
and not the longest common string '/home/user1/tmp/cove'
.
If your language has a routine that performs this function (even if it does not have a changeable separator character, then mention it as part of the task)
J
Solution: <lang j>parseDirs =: (PATHSEP_j_&= <;.2 ])@jhostpath getCommonPrefix =: ([: *./\ *./@({. ="1 }.)) ;@# {.
getCommonDirPath=: [: getCommonPrefix parseDirs&></lang>
Example: <lang j> paths=: '/home/user1/tmp/coverage/test';'/home/user1/tmp/covert/operator';'/home/user1/tmp/coven/members'
getCommonPrefix >paths
/home/user1/tmp/cove
getCommonDirPath paths
/home/user1/tmp/</lang>
Python
The Python os.path.commonprefix function is broken as it returns common characters that may not form a valid directory path: <lang python>>>> import os >>> os.path.commonprefix(['/home/user1/tmp/coverage/test', '/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members']) '/home/user1/tmp/cove'</lang>
This result can be fixed: <lang python>>>> def commonprefix(*args, sep='/'): return os.path.commonprefix(*args).rpartition(sep)[0]
>>> commonprefix(['/home/user1/tmp/coverage/test', '/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members']) '/home/user1/tmp'</lang>
But it may be better to not rely on the faulty implementation at all: <lang python>>>> def allnamesequal(name): return all(n==name[0] for n in name[1:])
>>> def commonprefix(paths, sep='/'): from itertools import takewhile bydirectorylevels = zip(*[p.split(sep) for p in paths]) return sep.join(x[0] for x in takewhile(allnamesequal, bydirectorylevels))
>>> commonprefix(['/home/user1/tmp/coverage/test', '/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members']) '/home/user1/tmp'</lang>
Tcl
<lang tcl>package require Tcl 8.5 proc pop {varname} {
upvar 1 $varname var set var [lassign $var head] return $head
}
proc common_prefix {dirs {separator "/"}} {
set parts [split [pop dirs] $separator] while {[llength $dirs]} { set r {} foreach cmp $parts elt [split [pop dirs] $separator] { if {$cmp ne $elt} break lappend r $cmp } set parts $r } return [join $parts $separator]
}</lang>
% common_prefix {/home/user1/tmp/coverage/test /home/user1/tmp/covert/operator /home/user1/tmp/coven/members} /home/user1/tmp