Find common directory path: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|PureBasic}}: some cleanup)
m (improve wording of task description)
Line 1: Line 1:
{{task}}
{{task}}
Create a routine that 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.
Create a routine that, given a set of strings representing directory paths and a single character directory separator, will 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:
Test your routine using the forward slash '/' character as the directory separator and the following three strings as input paths:
Line 25: Line 25:


=={{header|PureBasic}}==
=={{header|PureBasic}}==
{{incorrect|PureBasic|Although there are only three paths in the example the task asks for a routine that works on an arbitrary set of paths, and the separator should also be an argument to the routine}}

PureBasic don't have a path comparator directly but instead have powerful string tools.
PureBasic don't have a path comparator directly but instead have powerful string tools.


Simply by checking the catalog names until they mismatch and add up the correct parts, the task is accomplished.
Simply by checking the catalog names until they mismatch and add up the correct parts, the task is accomplished.
<lang PureBasic>S1$="/home/user1/tmp/coverage/test"
<lang PureBasic>Procedure.s CommonPath(Array InPaths.s(1),separator.s="/")
S2$="/home/user1/tmp/covert/operator"
Protected SOut$=""
S3$="/home/user1/tmp/coven/members"
Protected i, j, toggle
SOut$=""
i=1
If ArraySize(InPaths())=0
ProcedureReturn InPaths(0) ; Special case, only one path
EndIf
Repeat
i+1
toggle=#False
For j=1 To ArraySize(InPaths())
If (StringField(InPaths(j-1),i,separator)=StringField(InPaths(j),i,separator))
If Not toggle
SOut$+StringField(InPaths(j-1),i,separator)+separator
toggle=#True
EndIf
Else
ProcedureReturn SOut$
EndIf
Next
ForEver
EndProcedure</lang>

Example of implementation
<lang PureBasic>Dim t.s(2)
t(0)="/home/user1/tmp/coverage/test"
t(1)="/home/user1/tmp/covert/operator"
t(2)="/home/user1/tmp/coven/members"


While (StringField(S1$,i,"/")=StringField(S2$,i,"/")) And (StringField(S1$,i,"/")=StringField(S3$,i,"/"))
Debug CommonPath(t(),"/"))</lang>
SOut$+StringField(S1$,i,"/")+"/"
i+1
Wend
</lang>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 11:01, 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.

Create a routine that, given a set of strings representing directory paths and a single character directory separator, will 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>

PureBasic

This example is incorrect. Please fix the code and remove this message.

Details: Although there are only three paths in the example the task asks for a routine that works on an arbitrary set of paths, and the separator should also be an argument to the routine

PureBasic don't have a path comparator directly but instead have powerful string tools.

Simply by checking the catalog names until they mismatch and add up the correct parts, the task is accomplished. <lang PureBasic>S1$="/home/user1/tmp/coverage/test" S2$="/home/user1/tmp/covert/operator" S3$="/home/user1/tmp/coven/members" SOut$="" i=1

While (StringField(S1$,i,"/")=StringField(S2$,i,"/")) And (StringField(S1$,i,"/")=StringField(S3$,i,"/"))

 SOut$+StringField(S1$,i,"/")+"/"
 i+1

Wend </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>>>> from itertools import takewhile >>> def allnamesequal(name): return all(n==name[0] for n in name[1:])

>>> def commonprefix(paths, sep='/'): 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