一種方法是使用遞歸。這種方法不是最便宜的,但它確實具有靈活性的優勢 - 如果結構深度發生變化或在編譯時未知。
在僞碼:
integer count (collection , maxDepth)
return recursiveCount (collection , 0 , maxDepth)
end
integer recursiveCount (collection , currentDepth , maxDepth)
integer count = 0
if collection is array
count += recursiveCountArray (collection , currentDepth , maxDepth)
else if object is dictionary
count += recursiveCountDictionary (collection.values , currentDepth , maxDepth)
else
count += 1
return count
end
integer recursiveCountArray (array , currentDepth , maxDepth)
integer count = 0
if currentDepth < maxDepth
for (object in array)
count += recursiveCount(object)
else
count += array.count
return count
end
的maxDepth
參數確保沒有必要以上的工作已經完成(簡單地返回數組的計數時在MAXDEPTH而不是迭代的陣列上方和添加通過遞增計數@RamyAlZuhouri在他的評論中建議每次迭代一次)。
在Objective-C,這可能是與C函數來實現:
static NSUInteger _PFXRecursiveCount(id collection, NSUInteger currentDepth, NSUInteger maxDepth);
static NSUInteger _PFXRecursiveCountArray(id array, NSUInteger currentDepth, NSUInteger maxDepth);
NSUInteger PFXRecursiveCount(id collection, NSUInteger maxDepth)
{
return _PFXRecursiveCount(collection, 0, maxDepth);
}
NSUInteger _PFXRecursiveCount(id collection, NSUInteger currentDepth, NSUInteger maxDepth)
{
NSUInteger count = 0;
if ([collection isKindOfClass:[NSArray class]]) {
count = _PFXRecursiveCountArray(collection, currentDepth, maxDepth);
} else if ([collection isKindOfClass:[NSDictionary class]]) {
NSDictionary *dictionary = (NSDictionary *)collection;
count = _PFXRecursiveCountArray(dictionary.allValues, currentDepth, maxDepth);
} else {
count = 1;
}
return count;
}
NSUInteger _PFXRecursiveCountArray(NSArray *array, NSUInteger currentDepth, NSUInteger maxDepth)
{
NSUInteger count = 0;
if (currentDepth < maxDepth) {
for (id object in array) {
count += _PFXRecursiveCount(object, currentDepth + 1, maxDepth);
}
} else {
count += array.count;
}
return count;
}
這裏PFX
將與在你的項目中使用適當的前綴來代替。標題中只會聲明PFXRecursiveCount
。
可替代地,這可能是與塊來實現:
typedef NSUInteger (^RecursiveCountArrayBlock)(NSArray *, NSUInteger, NSUInteger);
typedef NSUInteger (^RecursiveCountBlock)(id, NSUInteger, NSUInteger);
__block __weak RecursiveCountArrayBlock _weakRecursiveCountArray = nil;
__block __weak RecursiveCountBlock _weakRecursiveCount = nil;
NSUInteger (^_recursiveCount)(id, NSUInteger, NSUInteger) = ^(id collection, NSUInteger currentDepth, NSUInteger maxDepth) {
NSUInteger count = 0;
if ([collection isKindOfClass:[NSArray class]]) {
count = _weakRecursiveCountArray(collection, currentDepth, maxDepth);
} else if ([collection isKindOfClass:[NSDictionary class]]) {
NSDictionary *dictionary = (NSDictionary *)collection;
count = _weakRecursiveCountArray(dictionary.allValues, currentDepth, maxDepth);
} else {
count = 1;
}
return count;
};
_weakRecursiveCount = _recursiveCount;
NSUInteger (^_recursiveCountArray)(id, NSUInteger, NSUInteger) = ^(NSArray *array, NSUInteger currentDepth, NSUInteger maxDepth) {
NSUInteger count = 0;
if (currentDepth < maxDepth) {
for (id object in array) {
count += _weakRecursiveCount(object, currentDepth + 1, maxDepth);
}
} else {
count += array.count;
}
return count;
};
_weakRecursiveCountArray = _recursiveCountArray;
NSUInteger (^recursiveCount)(id, NSUInteger) = ^(id collection, NSUInteger maxDepth) {
return _recursiveCount(collection, 0, maxDepth);
};
的__weak
__block
變量(_weakRecursiveCountArray
和_weakRecursiveCount
)使我們能夠避免從在其自身內的強引用該塊。 (注意:在iOS 5和10.7之前,__weak
需要替換爲__unsafe_unretained
。)typedefs允許我們避免虛假警告(「'__weak'僅適用於objective-c對象或塊指針類型;在此輸入是'NSUInteger'(又名'unsigned long')「)。
這就像一棵樹,你需要一個BFS,你停留在3級。 –
我不明白for循環如何比謂詞更昂貴,它會做同樣的事情,但以一種奇特的方式包裹起來。 – Jack
它可以得到一個簡單的只是總結最裏面的字典'count'值,而不是走他們。 –