【问题标题】:IOS: Merging two NSArrays while updating properties of "duplicates"IOS:在更新“重复”的属性时合并两个 NSArray
【发布时间】:2013-01-23 13:07:50
【问题描述】:

编辑:大量编辑,很抱歉造成混乱!

我目前正在开发一个应用程序,其中我使用两种不同的方法从 JSON WebService 获取 2 个数组。

在第一个数组中,我得到本地库存。在第二个数组中,我得到了供应商库存。

虽然我认为图片会更好地解释:

因此,Web 服务获取了许多商品。数组 1 包含来自本地库存的一些商品,数组 2 包含来自我们供应商的商品,并添加了描述等信息。我想合并两个数组,用供应商库存数组 2 中的项目描述更新我们本地 stock-array1 中的现有项目。

这是我想要实现的一个示例。所有产品都由唯一标识符属性(示例中未提及)标识,并且我已覆盖 isEqual 和 hash 来弥补这一点。如果一个产品有一个相似的 ID,它被认为是相同的。

**Product**

@property id *internalID;
@property id *externalID ;
@property id *localStock;
@property id *supplierStock;
@property id *image;
@property id *productInfo;

现在Webservice 1返回三个产品:

产品 1

*internalID = ABCDEF
*externalID = (null)
*localStock = 15
*supplierStock = (null)
*image = (null)
*productInfo = (null);

产品 2

*internalID = GHIJK
*externalID = (null)
*localStock = 13
*supplierStock = (null)
*image = niceImage.png
*productInfo = @"This Product is Awesome!";

产品 3

*internalID = LMNOP
*externalID = (null)
*localStock = 7
*supplierStock = (null)
*image = (null)
*productInfo = (null);

Webservice 2 返回四个产品,其中两个也在数组 1 中:

产品 1

    *internalID = (null)
    *externalID = 123456
    *localStock = (null)
    *supplierStock = 12
    *image = external_product1image.jpg
    *productInfo = @"This product is also Awesome and in both local stock and supplier stock!";

产品 4

    *internalID = (null)
    *externalID = 23456
    *localStock = (null)
    *supplierStock = 11
    *image = niceImage.png
    *productInfo = @"This Product is Awesome and only available from our supplier!";

产品 3

    *internalID = (null)
    *externalID = 78901
    *localStock = (null)
    *supplierStock = 7
    *image = external)supplierimage.jpg
    *productInfo = @"This product is also Awesome and in both local stock and supplier stock!";

那么mergedArray 应该是这样的:

产品 1

*internalID = ABCDEF
*externalID = 123456
*localStock = 15
*supplierStock = 12
*image = external_product1image.jpg
*productInfo = @"This product is also Awesome and in both local stock and supplier stock!";

//所以 Array 1 中的 Product 1 将其属性与 Array 2 中的 Product 1 合并

产品 2

*internalID = GHIJK
*externalID = (null)
*localStock = 13
*supplierStock = (null)
*image = niceImage.png
*productInfo = @"This Product is Awesome!";

产品 3

*internalID = LMNOP
*externalID = 78901
*localStock = 7
*supplierStock = 7
*image = external)supplierimage.jpg
*productInfo = @"This product is also Awesome and in both local stock and supplier stock!";

产品 4

*internalID = (null)
*externalID = 23456
*localStock = 13
*supplierStock = 11
*image = niceImage.png
*productInfo = @"This Product is Awesome and only available from our supplier!";

这是我使用的代码,但它似乎有时会以某种方式出现故障:

- (void) compareArrays:(id)sender metBreedte:(NSString *)breedte metHoogte:(NSString *)hoogte metDiameter:(NSString *)diameter
{
    NSMutableSet *getBandenSet = [NSMutableSet setWithArray:getBandenArray];      NSUInteger i = 0;

    while (i < [getBandenInfo1Array count]) {
        id getBandenInfo1Object = [getBandenInfo1Array objectAtIndex:i];
        if ([getBandenSet containsObject:getBandenInfo1Object])

        {

            BWBand *getBandenBand = [getBandenSet member:getBandenInfo1Object];

            BWBand *getBandenInfo1Band = getBandenInfo1Object;

            // Do stuff to the Banden (sync)
            getBandenBand.alternatievePrijs = getBandenInfo1Band.alternatievePrijs;
            getBandenBand.itemName = getBandenInfo1Band.itemName;
            getBandenBand.supplierStock = getBandenInfo1Band.supplierStock;
            getBandenBand.grossPrice = getBandenInfo1Band.grossPrice;
            getBandenBand.eancode = getBandenInfo1Band.eancode;
            getBandenBand.EMarked = getBandenInfo1Band.EMarked;
            getBandenBand.garagePrijs = getBandenInfo1Band.garagePrijs;
            getBandenBand.loadIndex = getBandenInfo1Band.loadIndex;
            getBandenBand.brand = getBandenInfo1Band.brand;
            getBandenBand.custPrice = getBandenInfo1Band.custPrice;
            getBandenBand.netPrice = getBandenInfo1Band.netPrice;
            getBandenBand.tyreLabel = getBandenInfo1Band.tyreLabel;
            getBandenBand.TyreLabelFuel = getBandenInfo1Band.TyreLabelFuel;
            getBandenBand.TyreLabelNoise = getBandenInfo1Band.TyreLabelNoise;
            getBandenBand.TyreLabelNoiseLevel = getBandenInfo1Band.TyreLabelNoiseLevel;
            getBandenBand.TyreLabelWet = getBandenInfo1Band.TyreLabelWet;
            getBandenBand.foto = getBandenInfo1Band.foto;
            NSMutableString *string1 = [NSMutableString stringWithString: getBandenBand.colorStock];
            NSString *newString = [string1 substringToIndex:[string1 length]-2];
            NSString *colorStock = [NSString stringWithFormat:@"%@-%@",newString,getBandenInfo1Band.supplierStock];
            getBandenBand.colorStock = colorStock;
           [getBandenSet removeObject:getBandenInfo1Object];
            [getBandenInfo1Array removeObjectIdenticalTo:getBandenInfo1Object];
        } else
        {i++;}

        mergedBandenArray = [NSMutableArray arrayWithArray:[getBandenArray arrayByAddingObjectsFromArray:getBandenInfo1Array]];
       [mergedBandenArray sortUsingDescriptors:
         [NSArray arrayWithObjects:
          [NSSortDescriptor sortDescriptorWithKey:@"colorStock" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"brand" ascending:YES], nil]];}

所有这些都可以使用 NSPredicates 完成吗?如果有,怎么做?

提前致谢!

【问题讨论】:

  • 您的 TableViewController 是在您的 while 循环完成后分配的,所以这不应该是您的问题。
  • 仍在检查我的代码。如果有人知道使用 NSPredicates 进行这种比较的更优雅的解决方案,我会全神贯注:)。
  • 您是否为您的对象正确设置了哈希和相等操作,以便两个对象比较相等,即使它们是您要合并的不同内部数据?
  • 要使表格视图正确刷新,只需在合并完成后发出刷新。或者在你准备好之前根本不显示表格。
  • 是的,抱歉,忘记提了。我正在使用 AFNetworking 异步填充两个数组,然后在 AFHTTPClient 的完成块中运行上述代码。如果只有一个唯一标识符相同,我已经覆盖了哈希和 isEqualto 以使它们“相等”。

标签: objective-c merge comparison nsarray nspredicate


【解决方案1】:

以下算法不需要您为 Product 类覆盖 isEqualhash

  • 首先根据uniqueItemID键升序对两个数组进行排序。
  • 然后并行遍历两个数组,并将两个数组中的产品添加或合并到目标数组。

如果两个数组都已排序,则可以通过并行遍历两个数组的单个循环轻松找到匹配和不匹配的产品。

以下代码有望证明这一想法:

NSSortDescriptor *sortByID = [NSSortDescriptor sortDescriptorWithKey:@"uniqueItemID" ascending:YES];
NSArray *sorted1 = [array1 sortedArrayUsingDescriptors:@[sortByID]];
NSArray *sorted2 = [array2 sortedArrayUsingDescriptors:@[sortByID]];

NSUInteger i1 = 0, i2 = 0;
NSMutableArray *combined = [NSMutableArray array];
while (i1 < [sorted1 count] && i2 < [sorted2 count]) {
    Product *p1 = sorted1[i1];
    Product *p2 = sorted2[i2];
    switch ([p1.uniqueItemID compare:p2.uniqueItemID]) {
        case NSOrderedAscending:
            // p1 is in first array, but not in second:
            [combined addObject:p1];
            i1++;
            break;
        case NSOrderedDescending:
            // p2 is in second array, but not in first:
            [combined addObject:p2];
            i2++;
            break;
        case NSOrderedSame:
            // p1, p2 have same ID:
            ... update p1 with values from p2 ...
            [combined addObject:p1];
            i1++, i2++;
            break;
    }
}
// Add remaining products from first array:
while (i1 < [sorted1 count]) {
    [combined addObject:sorted1[i1]];
    i1++;
}
// Add remaining products from second array:
while (i2 < [sorted2 count]) {
    [combined addObject:sorted2[i2]];
    i2++;
}

【讨论】:

  • 刚刚在我的代码中测试过,比我原来的代码快了几秒,谢谢!
  • @VincentVeldkamp:不客气! - 请问您的数组有多少条目,实际时间是多少(旧/新代码)? - 仅当您可以共享该信息时,否则请忽略此问题!
  • 嗯,大约有 200 多个条目,具体取决于搜索。包含大量需要过滤的属性的类。我采用了资源最密集的搜索查询,有时我的代码在 6 到 7 秒的时间内完成,而你的代码则以 3.57 到 5 秒的速度运行。(在此期间我们也遇到了一些网络延迟问题)。所以我会说这是相当的进步!无论如何,您的代码也更易于阅读。再说一次,我对自己的代码没有太大的期望,因为我 5 个月前才开始编程。在某个地方我知道它可以更有效!编辑:输入 500 个条目,呵呵
【解决方案2】:

1)。合并两个数组:

NSMutableSet *set = [NSMutableSet setWithArray:array1]; [设置 addObjectsFromArray:array2]; NSArray *array = [设置所有对象];

2)。在 NSPredicates 的帮助下删除重复项:

1. Filtering Fun with Predicates

2. Hello, NSPredicate

3)。合并和删除重复项:

NSArray *array1, *array2; MSMutableArray *result = [array1 mutableCopy]; for (array2 中的 id 对象) { [结果删除对象:对象]; // 如果已经存在,则删除重复项。 [结果添加对象:对象]; }

【讨论】:

  • 以上只是一个有更好想法的逻辑。此外,我不知道响应数据格式。根据提到的图像,两个数组都应该有一个唯一的键来识别对象重复。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 2019-11-25
  • 2013-11-02
  • 2019-04-17
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多