开发者

How can I get the common ancestor directory for two or more files in Cocoa/Obj-C?

I have a bunch of files, either NSStrings or NSURLs (it doesn't ma开发者_开发知识库tter; they are, for the most part, interchangeable), and I need a way to find the common ancestor directory. Does anyone know how to do this?


I could have sworn there was a pathByJoiningPathComponents method somewhere, or at least one like it, but I must be thinking of something else. This does the trick for paths, it may work for URLs too if you're on 10.6 (I only tested it with paths):

NSString *path1 = @"/path/to/file1.txt";
NSString *path2 = @"/path/to/file/number2.txt";

NSArray *path1Comps = [path1 pathComponents];
NSArray *path2Comps = [path2 pathComponents];

NSUInteger total = [path1Comps count];
if ([path2Comps count] < total)
    total = [path2Comps count];  // get the smaller of the two

NSUInteger i;
for (i = 0; i < total; i++)
    if (![[path1Comps objectAtIndex:i] isEqualToString:[path2Comps objectAtIndex:i]])
        break;

NSArray *commonComps = [path1Comps subarrayWithRange:NSMakeRange(0, i)];

// join commonComps together to get the common path as a string

I don't think there is a “built-in” way to do it, unfortunately.

If you have an array of file paths that you want to find the common ancestor, you could do something like this:

NSArray *allPaths = [NSArray arrayWithObjects:@"/path/to/1.txt", @"/path/to/number/2.txt", @"/path/to/number/3/file.txt", nil];

// put some checks here to make sure there are enough paths in the array.

NSArray *currentCommonComps = [[allPaths objectAtIndex:0] pathComponents];

for (NSUInteger i = 1; i < [allPaths count]; i++)
{
    NSArray *thisPathComps = [[allPaths objectAtIndex:i] pathComponents];
    NSUInteger total = [currentCommonComps count];
    if ([thisPathComps count] < total)
        total = [thisPathComps count];

    NSUInteger j;
    for (j = 0; j < total; j++)
        if (![[currentCommonComps objectAtIndex:j] isEqualToString:[thisPathComps objectAtIndex:j]])
            break;

    if (j < [currentCommonComps count])
        currentCommonComps = [currentCommonComps subarrayWithRange:NSMakeRange(0, j)];

    if ([currentCommonComps count] == 0)
        break; // no point going on
}

// join currentCommonComps together

You may want to explicitly allocate and release some of these objects if you want to keep the autorelease pool clean, especially if you have a large array of paths.


Represent the paths as NSArrays of components. (In Mac OS X 10.6 and later, send each object a pathComponents message; in earlier versions and on the iPhone OS, you'll need to send NSURL objects path messages to get NSStrings, then send those the pathComponents messages.)

Have an NSMutableArray containing the common path so far. Initialize it to the first path's components.

For each subsequent path, iterate both that path and the current path so far in lockstep using NSEnumerators.

  • If the common path so far runs out, no change.
  • If the path you're examining runs out, it is the new common path.
  • If you encounter an inequal component, all components before it are the new common path. Break the lockstep iteration here.

When you finish, you'll have an array of zero or more path components. Joining these into an absolute path string will produce the common path string.


Take a file, take the next file, iterate through its ancestors (NSString's pathComponents method will be useful for this) until you find one that they have in common. Then move onto the next file, see if it has the same ancestor. If not, keep going back until you find one they do have in common. Keep repeating this until you reach the end of the list.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜