AhabLives
AhabLives

Reputation: 1468

How to loop through and add duplicates in an Array

I have a Dictionary with an Orders array with amount and orders in it Orders = ("3 White Shirts", "8 White Shirts", "4 blue shorts")

How would I loop through it and add the amount of duplicate orders so that the result string or array would be Orders = ("11 White Shirts", "4 blue shorts") or myString ="11 White Shirts, 4 blue shorts"

I'm thinking some sort of substring to check if the products are the same but not sure how to capture the correct quantity to add from the duplicate order

Many thanks

Upvotes: 1

Views: 244

Answers (3)

Alladinian
Alladinian

Reputation: 35636

Ok here is a way to do this (the shortest one I could think of):

// Assuming that 'orders' is the array in your example
NSMutableDictionary *orderDict = [[NSMutableDictionary alloc] init]; 

for (NSString *order in orders)
{
    // Separate the string into components
    NSMutableArray *components = [[order componentsSeparatedByString:@" "] mutableCopy];

    // Quantity is always the first component
    uint quantity = [[components objectAtIndex:0] intValue];
    [components removeObjectAtIndex:0];

    // The rest of them (rejoined by a space is the actual product)
    NSString *item = [components componentsJoinedByString:@" "];

    // If I haven't got the order then add it to the dict
    // else get the old value, add the new one and put it back to dict
    if (![orderDict valueForKey:item])
        [orderDict setValue:[NSNumber numberWithInt:quantity] forKey:item];
    else{
        uint oldQuantity = [[orderDict valueForKey:item] intValue];
        [orderDict setValue:[NSNumber numberWithInt:(oldQuantity+quantity)] forKey:item];
    }
}

This would give you a dict like this:

{
    "White Shirts" = 11;
    "blue shorts" = 4;
}

So you could iterate over the keys and produce an array of strings like this:

NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:0];
for (NSString *key in [orderDict allKeys])
{
    [results addObject:[NSString stringWithFormat:@"%@ %@", [orderDict valueForKey:key], key]];
}

Which finally will give you:

(
    "11 White Shirts",
    "4 blue shorts"
) 

PS. Don't forget to release if you don't use ARC !

Upvotes: 2

user1558505
user1558505

Reputation:

Since it looks like your array contains string objects, I would do something like this:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        NSArray *ordersAsStrings = [NSArray arrayWithObjects:@"7 white shirts", @"4 blue jeans", @"3 white shirts", @"4 blue jeans", nil];
        NSMutableDictionary *combinedQuantities = [NSMutableDictionary new];
        NSMutableArray *combinedOrdersAsStrings = [NSMutableArray new];

        // take each string and break it up into the quantity and the item
        for (NSString *orderAsString in ordersAsStrings) {
            NSInteger scannedQuantity = 0;
            NSString *scannedItem = nil;
            NSScanner *scanner = [NSScanner scannerWithString:orderAsString];
            [scanner scanInteger:&scannedQuantity];
            [scanner scanCharactersFromSet:[[NSCharacterSet illegalCharacterSet] invertedSet] intoString:&scannedItem];

            // if the item is already in combinedOrders
            if ([combinedQuantities.allKeys containsObject:scannedItem] == YES) {
                // update quantity
                NSNumber *existingQuantity = [combinedQuantities objectForKey:scannedItem];
                NSInteger combinedQuantity = existingQuantity.integerValue + existingQuantity.integerValue;
                [combinedQuantities setObject:[NSNumber numberWithInteger:combinedQuantity] forKey:scannedItem];
            } else {
                // otherwise add item
                NSNumber *quantity = [NSNumber numberWithInteger:scannedQuantity];
                [combinedQuantities setObject:quantity forKey:scannedItem];
            }
        }

        // change combined quantities back into strings
        for (NSString *key in combinedQuantities.allKeys) {
            NSNumber *quantity = [combinedQuantities objectForKey:key];
            NSString *orderAsString = [NSString stringWithFormat:@"%ld %@", quantity.integerValue, key];
            [combinedOrdersAsStrings addObject:orderAsString];
        }

        NSLog(@"Combined Orders: %@", combinedOrdersAsStrings);
    }
    return 0;
}

Upvotes: 0

Analog File
Analog File

Reputation: 5316

You need to parse the strings to extract the two pieces of information: order quantity, which is a numeric value, and item identification, which may remain a string.

Use a NSMutableDictionary mapping the item identification to a numeric value representing the current order quantity, else retrieve the old total and add to it the current order, then update the dictionary.

At the end iterate the dictionary and transform each key-value pair back into a string.

Upvotes: 0

Related Questions