0

i know that the question sounds wears.I couldn't find a better way to put it so i will take my time to explain the question i m struggling with.

I have an iPhone app that takes input from user.And i got a plist ( i will convert it to a online database soon) What i currently do is this. I compare my input string with ingredients part of items in my plist.

This is the plist format

<array>
    <dict>
        <key>category</key>
        <string>desert</string>
        <key>numberOfPerson</key>
        <string>3</string>
        <key>recipeImage</key>
        <string>asd.jpg</string>
        <key>time</key>
        <string>15</string>
        <key>recipeName</key>
        <string>Puding</string>
        <key>recipeDetail</key>

i compare the input with recipeIngredients.But what my codes do is not what i need.If the comparison turns true i just list every item from my plist that contain the input ingredients.I can filter through selected recipes but what i want is this: Unless there is a full match up with input and ingredients i do not want to show it.

The problem is this. I got my recipe ingredients like this format 1 spoon of sugar, 1 spoon of salt, 100g chicken.

The user enter inputs like - salt , sugar. chicken so i can not fully compare it.It will never be the same so i can not show anything.

How can i accomplish this.

i m open for any kind of suggestions.

This is how i compare

    results = [arrayOfPlist filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
        NSDictionary *_dataRow = (NSDictionary *)evaluatedObject;
        return ([[[_dataRow valueForKey:@"recipeIngredients"] lowercaseString] rangeOfString:[searchText lowercaseString]].location != NSNotFound);
    }]];

where searchText is my input.

ZeMoon
  • 20,054
  • 5
  • 57
  • 98
user3570579
  • 65
  • 1
  • 8
  • A couple of questions: 1) is recipeIngredients an array of strings, or just one big string? 2) are you wanting to return recipes for which you have all the ingredients, or recipes which contain all the ingredients you have? – David Berry Apr 25 '14 at 21:59
  • @David 1)its just a big string. 2)yes i will return recipes that have all the ingredients – user3570579 Apr 25 '14 at 22:02

4 Answers4

1

First of all, you'll never know if there is a typo in user input.

But what you can do is before you compare two strings, you can do a little bit trimming for a given character set. There is a method in NSString class called :

- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set

If you want to get rid of . or - characters, you need to specify them in your character set. Than, you can compare two strings.

limon
  • 3,222
  • 5
  • 35
  • 52
1

Using -[NSPredicate predicateWithFormat:] you can do database-esque string comparisons. For instance, you could try

[NSPredicate predicateWithFormat:@"recipeIngredients CONTAINS[cd] %@", searchText]

Check out https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html the section called "String Comparisons"

EDIT: if the user will be searching multiple things at once, like "chicken, noodle," you can be a little more fancy and do:

NSArray *tokens = [[searchText componentsSeparatedByCharactersInSet:NSCharacterSet.alphanumericCharacterSet.invertedSet] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"];
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"recipeIngredient CONTAINS[cd] (ANY %@)", tokens]
Adlai Holler
  • 830
  • 7
  • 10
  • Thats a great way to compare and do what i want to do.Awesome.One more question.How am i suppose to use this? IS this returns a boolean? And no the user will enter one input at a time but thanks for that aswel :) – user3570579 Apr 25 '14 at 22:12
  • Are you sure that your predicate is valid? That's similar to what I first tried, so I tried yours as well, and it throws an exception that it can't parse the predicate. – David Berry Apr 25 '14 at 22:35
  • user3570579 you can use it in a couple of ways. For your case you probably want `[arrayOfPlist filteredArrayUsingPredicate:[NSPredicate predicateWithFormat…]]`. You can also manually evaluate an object like `BOOL isAResult = [[NSPredicate predicateWithFormat…] evaluateWithObject:dataRow]` – Adlai Holler Apr 27 '14 at 23:09
0

You should split up the searchText into an array by using -componentsSeparatedByString:@",", and then loop through the array to see if the recipeIngredients contains any of the ingredients in the searchText array. In order to work out if the query contains every single ingredient, you can create an integer inside of the block and increment it everytime you have a match. If the number of matches is equal to the number of ingredients, then you can go from there.

max_
  • 24,076
  • 39
  • 122
  • 211
0

The code below builds up a predicate that boils down to "ingredients contains sugar and ingredients contains chocolate"

NSArray*        recipes = @[
                            @{@"recipeIngredients": @"sugar flour chocolate"},
                            @{@"recipeIngredients": @"sugar chocolate"},
                            @{@"recipeIngredients": @"flour chocolate"},
                            @{@"recipeIngredients": @"chocolate"},
                            ];
NSString*       search = @"sugar, chocolate";

// split the ingredients we have into an array of strings separated by ',' or ' '
NSArray*        haves = [search componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@", "]];

// Build a list of recipeIngredients CONTAINS have
NSMutableArray* ands = [NSMutableArray new];
for(NSString* have in haves)
{
    if(have.length > 0)
    {
        [ands addObject:[NSPredicate predicateWithFormat:@"recipeIngredients CONTAINS[cd] %@", have]];
    }
}

// String all the haves into a single long ... AND ... AND ... predicate    
NSPredicate*    predicate = [NSCompoundPredicate andPredicateWithSubpredicates:ands];

// Apply the predicate
NSArray*        filtered = [recipes filteredArrayUsingPredicate:predicate];
David Berry
  • 40,941
  • 12
  • 84
  • 95
  • thank you for your effort but thats not really different from what i did.I It add the recipe to the filteredArray without checking all ingredients.If it have what the predicate contains it add to the filteredArray – user3570579 Apr 25 '14 at 22:26