【问题标题】:Level, depth of a directory from my computer我的计算机中目录的级别,深度
【发布时间】:2016-04-21 14:36:51
【问题描述】:

我有两个目录路径:
Path 1 = "C:\Users\SomeUser\Documents\Embarcadero\Studio\"
Path 2 = "C:\Users\SomeUser\Documents\"
如您所见,Path 1Path 2 深两层
换句话说,路径 1 深度为 6,路径 2 深度为 4
我需要一个可以计算这个深度的函数

编辑:
这是误解我问题的任何人的另一个例子

Path A :="c:\"  {This is level 1 or depth 1}  
Path B := "c:\foo"  {This is level 2 or depth 2}  
Path C := "c:\bar"  {This is level 2 or depth 2}  
Path D := "c:\foo\folder1"  {this is level 3 or depth 3}  
Path E := "c:\bar\folder2"  {this is level 3 or depth 3}  

我认为现在很清楚,当我说 depth 时,我的意思是如果我在驱动器 C 中我应该潜多深才能到达最终文件夹
我为什么需要这个?
因为在我的程序中,用户从他给出的基本目录中设置深度,我必须搜索并找到该基地根目录中的所有文件(如果深度为 1),例如深度为 2 我也必须在根目录中的任何文件夹内进行搜索,如果是 3,我将在该文件夹位于根目录的另一个文件夹内的文件夹内搜索任何文件
我的程序中的另一个功能也需要我需要的距离或深度差异,可以计算为

abs(depthFolder1 - depthFolder 2)

【问题讨论】:

  • C:\foo 和 C:\bar 之间的预期距离是多少? C:\foo 和 D:\baz 之间怎么样?
  • @RobKennedy 显然是“0”
  • "0" 好像不对,C:\foo 和 C:\foo 呢?
  • 对我来说并不明显,尽管它确实是您的函数将返回的内容。 C:\foo\quux 和 C:\bar 之间的距离呢?把它想象成一棵树,我会说距离是 3。(绘制节点,然后计算从一片叶子到另一片叶子的边。)我会说从 C:\ 到 D:\ 的距离未定义,因为树没有根节点。 Sertac 的示例显然为零。
  • @RobKennedy,在 C:\ 和 D:\ 之间有一个 根音,即MyComputer。这取决于...

标签: delphi delphi-xe2


【解决方案1】:
const 
  Path1 = "C:\Users\SomeUser\Documents\Embarcadero\Studio\";
  Path2 = "C:\Users\SomeUser\Documents\";

var 
  sl1, sl2: iJclStringList;

procedure Init(out sl: iJclStringList; const CanonicalPath: string);
begin
  sl := JclStringList();
  sl.Split( AnsiUpperCase( CanonicalPath ), '\' );
  if sl.Count <= 0 then exit;
  if sl.Last = '' then sl.Delete( sl.LastIndex );
end;

var i: integer;

begin
  Init( sl1, Path1 );
  Init( sl2, Path2 );

  i := 0;
  while (i < sl1.Count) and (i < sl2.Count)
    and (sl1[i] = sl2[i]) 
  do
      Inc(i);

  // now i maps to the first different element
  Difference := Max(sl1.Count, sl2.Count) - i;

  sl1 := nil;
  sl2 := nil;
end;

http://wiki.delphi-jedi.org/wiki/Category:IJclStringList_Methods

【讨论】:

    【解决方案2】:

    获取两条路径的差,统计\的个数。

    未经测试,因为没有打开Delphi

    uses Math;
    
    function GetSamePart(const A,B: string): string;
    var
      i: integer;
      MinLen: integer;
    begin
      i:= 0;
      MinLen:= Min(Length(A), Length(B));
      while i < MinLen do begin
        if lowercase(A[i+1]) = Lowercase(B[i+1]) then inc(i)
        else break;
      end; {while}
      if i = 0 then Result:= ''
      else Result:= Copy(A, 1, i);
    end;
    
    function OccurrencesOfChar(const S: string; const C: char): integer;
    var
      i: Integer;
    begin
      result := 0;
      for i := 1 to Length(S) do
        if S[i] = C then
          inc(result);
    end;
    
    function CountPaths(const Pathname: string; PathChar: char = '\'): integer;
    begin
      if PathName = '' then Exit(0);
      Result:= OccurrencesOfChar(PathName, PathChar);
      if PathName[Length(PathName)] <> PathChar then Inc(Result);
    end;
    
    function GetPathDistance(const A,B: string): integer;
    var
      ADiff, BDiff: string;
      FirstDiff: integer;
    begin
      FirstDiff:= Length(GetSamePart(A,B));
      if FirstDiff < Length(A) then ADiff:= Copy(A, FirstDiff+1, Length(A)-FirstDiff);
      if FirstDiff < Length(B) then BDiff:= Copy(B, FirstDiff+1, Length(B)-FirstDiff);
      Result:= CountPaths(ADiff) + CountPaths(BDiff);
    end;
    

    【讨论】:

    • 看起来区分大小写:-P
    • 是的,这是我的终极路径距离计数库的 alpha 预发布版本。
    【解决方案3】:
    function GetDirLevel(aDirectory: string): integer;
    var
      a_Index: integer;
    begin
      Result := 0;
      aDirectory := IncludeTrailingPathDelimiter(aDirectory);
      for a_Index := 1 to Length(aDirectory) do
        if IsPathDelimiter(aDirectory, a_Index) then
          inc(Result);
    end;
    
    function GetComparedLevel(aBase, aDirectory: string): integer;
    begin
      aBase := IncludeTrailingPathDelimiter(aBase);
      aDirectory := ExtractRelativePath(aBase, aDirectory);
      if POS('..', aDirectory) = 1 then
        Result := -1
      else
        Result := GetDirLevel(aDirectory);
    end;
    

    这使用RelativePath 到基础来确定级别。因此,如果您的目录不在 BaseDir 中,它将返回 -1。

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Label1.Caption := IntToStr(GetComparedLevel('c:\temp', 'c:\temp\level2\level3\level4'));//will return 3
      Label2.Caption := IntToStr(GetComparedLevel('c:\temp\level', 'c:\temp\level2\level3\level4'));//will return -1
    
    end;
    

    【讨论】:

      【解决方案4】:

      首先我感谢所有其他答案
      但在其他人发布他们的答案之前,我已经找到了我的

      function findPathDepth(path: String): integer;
      var
        I: Integer;
        depthCounter: Integer;
      begin
        depthCounter := 0;
        // path.Length - 2 in case there is an extra "\" at the end
        for I := 0 to path.Length - 2 do
          if (path[i] = '\') then
            inc(depthCounter);
      
        Result := depthCounter;
      end;
      
      function findPathDepthDistance(path1: String; path2: String): integer;
      begin
        if (ExtractFileDrive(path1) = ExtractFileDrive(path2)) then
            Result := abs(findPathDepth(path1) - findPathDepth(path2));
        else 
            Result := -1;
      end;  
      

      再次感谢。

      【讨论】:

      • 您的代码认为 "C:\foo\bar\" 和 "C:\bar\" 之间的距离为 1。
      • @Sertac:确实。我真的很想知道他认为两个不相关目录之间的深度是多少。
      • 他说它是零,@Rudy,“显然。”
      • @SertacAkyuz 好吧,我希望它返回 1,出于我的目的,1 是正确答案,在我的书中,如果 c:\ 是 1 级,里面的任何其他文件夹都是 2 级,如果有是这些文件夹中的另一个文件夹,它们都是第 3 级,这是我需要知道的,这就是我的函数返回的内容,如果其他人需要其他东西,他们可以根据自己的需要进行更改。
      • 你真的应该删除整个问题,因为它对任何人都没有用。你应该在问之前仔细考虑一下。
      猜你喜欢
      • 2011-08-27
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      • 2016-05-13
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      相关资源
      最近更新 更多