Find common directory path: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Tcl}}: Corrected to allow arbitrary separators)
Line 50: Line 50:


=={{header|Tcl}}==
=={{header|Tcl}}==
<lang tcl>proc pop {varname {nth 0}} {
<lang tcl>package require Tcl 8.5
upvar $varname args
proc pop {varname} {
set head [lindex $args $nth]
upvar 1 $varname var
set args [lreplace $args $nth $nth]
set var [lassign $var head]
return $head
return $head
}
}


proc common_prefix {dirs} {
proc common_prefix {dirs {separator "/"}} {
set parts [file split [pop dirs]]
set parts [split [pop dirs] $separator]
while {[llength $dirs]} {
while {[llength $dirs]} {
set r {}
set r {}
foreach cmp $parts elt [file split [pop dirs]] {
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 [eval file join $parts]
return [join $parts $separator]
}</lang>
}</lang>



Revision as of 09:11, 24 March 2010

Task
Find common directory path
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