【问题标题】:removing duplicate profiles loaded from an xml file using NSPredicate使用 NSPredicate 删除从 xml 文件加载的重复配置文件
【发布时间】:2014-01-03 17:49:42
【问题描述】:

我正在创建一个应用程序,该应用程序加载一个带有来自网络的配置文件列表的 XML 文件。按下时有一个按钮可在 textView 中显示所有配置文件。

现在我想要另一个按钮来从 textView 上的该列表中删除重复的配置文件,感谢任何有关如何做到这一点的帮助!

我有一个:

NSMutableDictionary *profileDict;

NSMutableArray *profile;

NSArray *profileArr;

我已经研究过如何做到这一点,但找不到与我需要的东西相关的东西。我读过一些关于 NSPredicate 的东西,但我是新手,不知道如何让它在我的项目中工作。

这是在 textView 中显示配置文件的按钮的代码:

- (IBAction)showProfilesButton:(id)sender
{
    XMLParser* parser = [[XMLParser alloc]init]; //This is loading the XMLParser class
    [parser loadXML];

    NSMutableString *str = [[NSMutableString alloc] init];

    for(NSMutableDictionary *obj in [[Globals globalBinding]globalArr])
    {
        [str appendFormat:@"\n %@", [obj objectForKey:@"firstname"]];
    }
    [self.profilesLabelTextView setText:str];
}

用于删除重复项的 IBAction:

- (IBAction)removeDuplicates:(id)sender
{
    //How should I start here.....?
}

编辑:支持问题的其余课程

我已经把其余的类放在下面以使一切清楚。

XMLParser.h

#import <Foundation/Foundation.h>
#import "ViewController.h"

@interface XMLParser : NSObject

{
    bool isStatus;
    XMLParser *currentProfile;
    XMLParser *xmlParser;
    NSXMLParser *parser;
    NSMutableString *currentNodeContent;
    NSMutableArray *profile;
    NSString *firstName;
}

- (void)loadXMLByURL:(NSString *)urlString;
- (void)loadXML;

- (NSString *)firstName;

@property (strong,nonatomic) NSMutableDictionary *profileDict;
@property (strong,nonatomic) NSMutableArray *profile;
@property (strong,nonatomic) NSArray *profileArr;

@end

XMLParser.m

#import "XMLParser.h"
#import "Globals.h"

@implementation XMLParser
-(id)loadXMLByURL:(NSString *)urlString
{
    self.profileDict=[NSMutableDictionary dictionary];
    self.profile=[[NSMutableArray alloc]init];
    self.profileArr=[[NSArray alloc]init];
    NSURL *url = [NSURL URLWithString:@"http://dierenpensionlindehof.nl/profiles1.xml"];
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    [parser parse];
    return self;
}


-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if([elementName isEqualToString:@"firstname"])
    {
        currentProfile = [XMLParser alloc];
        isStatus = YES;
    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if([elementName isEqualToString:@"firstname"])
    {

        currentProfile->firstName = currentNodeContent;
    //    NSLog(@"%@",currentProfile->firstName);
        [self.profileDict setObject:currentProfile->firstName forKey:@"firstname"];
    }

    if([elementName isEqualToString:@"profile"])
    {
        [self.profile addObject:self.profileDict];
        self.profileDict=[NSMutableDictionary dictionary];
        [[Globals globalBinding]setGlobalArr:self.profile];
    }
}

-(void)loadXML
{
    [self loadXMLByURL:@"http://dierenpensionlindehof.nl/profiles1.xml"];
}

-(NSString *)firstName
{
    return firstName;
}

@end

ViewController.h

#import <UIKit/UIKit.h>
#import "XMLParser.h"

@interface ViewController : UIViewController
{

}

@property (weak, nonatomic) IBOutlet UITextView *profilesLabelTextView;

@end

ViewController.m

#import "ViewController.h"
#import "XMLParser.h"
#import "Globals.h"

@interface ViewController ()

@end

@implementation ViewController
 - (IBAction)removeDuplicates:(id)sender
{
}

//Code for the button to display the profiles
- (IBAction)showProfilesButton:(id)sender
{
    XMLParser* parser = [[XMLParser alloc]init];
    [parser loadXML];

    NSMutableString *str = [[NSMutableString alloc] init];

    for(NSMutableDictionary *obj in [[Globals globalBinding]globalArr])
    {
        [str appendFormat:@"\n %@", [obj objectForKey:@"firstname"]];
    }

    [self.profilesLabelTextView setText:str];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

Global.h

#import <Foundation/Foundation.h>

@interface Globals : NSObject
@property (strong, nonatomic)NSMutableArray *globalArr;
+(Globals*)globalBinding;

@end

Global.m

#import "Globals.h"
static Globals *global=nil;

@implementation Globals

+(Globals*)globalBinding
{
    if (global == nil) {
        global = [[Globals alloc]init];
    }
    return global;
}

@end

【问题讨论】:

    标签: ios objective-c nsmutablearray nsdictionary nspredicate


    【解决方案1】:

    不知道您的数据格式,无法回答。但是,一般的答案是使用关键路径运算符“distinctUnionOfObjects”。

    例如,如果您有一个要解析的字符串列表。

    NSArray* array = @[@"A", @"B", @"C", @"B"];
    NSArray* uniqueValues = [array valueForKeyPath:@"@distinctUnionOfObjects.self"];
    
    // will results in uniqueValues array containing A, B, C
    

    或者,如果您有一个包含对象的数组,并且这些对象每个都有一个您希望使其唯一的属性(例如“名称”),您可以执行以下操作。

    NSArray* uniqueValues = [array valueForKeyPath:@"@distinctUnionOfObjects.name"];
    

    如果不了解您的字典或对象结构的更多信息,恐怕我们无法获得比这更详细的信息。

    坦率地说,这只是给众所周知的猫剥皮的众多方法之一。它适用于简单的数据和数据结构,但随着事情变得更加复杂,它可能会崩溃。

    编辑:

    要处理您的具体情况,请使用以下示例。如您所见,它从包含字典的数组中获取不同的名字,每个字典都有一个“名字”项。

    NSDictionary* dict1 = @{ @"firstname" : @"A" };
    NSDictionary* dict2 = @{ @"firstname" : @"B" };
    NSDictionary* dict3 = @{ @"firstname" : @"C" };
    NSDictionary* dict4 = @{ @"firstname" : @"A" };
    
    NSArray* array = @[ dict1, dict2, dict3, dict4 ];
    
    NSLog(@"Distinct Values = %@", [array valueForKeyPath:@"@distinctUnionOfObjects.firstname"]);
    // prints out "Distinct Values = (A, B, C)"
    

    【讨论】:

    • 感谢您的快速回复,我已经添加了其余的类,以便您查看数据格式等。希望您现在可以理解它。谢谢
    • 你的最终结果是什么?一个包含 NSDictionaries 列表的 NSMutableArray,每个都有一个条目,名字?
    • 是的,我希望能够删除重复的名字,例如,如果列表中有 2 个约翰,我想删除一个..
    • 嗨,Travis,你能帮我解决这个问题吗,我尝试了所有方法,但到目前为止没有运气。
    • 您好,抱歉耽搁了。我已经离开了。无论如何,您可以轻松扩展我给出的示例以获得不同的列表。这是一些示例代码。 NSDictionary* dict1 = @{ @"firstname" : @"A" }; NSDictionary* dict2 = @{ @"firstname" : @"B" }; NSDictionary* dict3 = @{ @"firstname" : @"C" }; NSDictionary* dict4 = @{ @"firstname" : @"A" }; NSArray* 数组 = @[ dict1, dict2, dict3, dict4 ]; NSLog(@"Values = %@", [array valueForKeyPath:@"@distinctUnionOfObjects.firstname"]);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多