【问题标题】:Filtering a dictionary by the value for a key in the sub dictionaries with a UISearchBar使用 UISearchBar 按子字典中键的值过滤字典
【发布时间】:2009-08-19 19:42:24
【问题描述】:

(注意:这是previous question的扩展。)

我在为相当复杂的 tableview 实现 SearchBar 时遇到了一些困难。 tableView 有多个部分,两行文本和一个图像。所有数据都从 plist 加载,然后按“名称”键值的首字母放入部分中。 NSLog 为我的主字典“sectionedDictionaryByFirstLetter”返回以下内容:

sectionedDictionaryByFirstLetter:{
B = (
  {
    Name = "B...A Name Starting with B";
    Image = "ImageName1.png";
    Text = "Some Text";
  }
    );
C = (
  {
    Name = "C...A Name Starting with C";
    Image = "ImageName2.png";
    Text = "Some Text";
  }
    );
N = (
  {
    Name = "N1...A Name Starting with N";
    Image = "ImageName3.png";
    Text = "Some Text";
  },
  {
    Name = "N2...A Name Starting with N";
    Image = "ImageName4.png";
    Text = "Some Text";
  },
  {
    Name = "N3...A Name Starting with N";
    Image = "ImageName5.png";
    Text = "Some Text";
  }
  );
}

我想按“名称”键的值过滤子词典。任何人都可以推荐如何进行此操作或一些学习方法的资源吗?我一直在遵循“开始 iPhone 3 开发”中的示例,但无法将其转化为我的情况。 因此,如果用户在搜索栏中键入“with N”,我希望新字典显示为:

    filteredSectionedDictionaryByFirstLetter:{
N = (
  {
    Name = "N1...A Name Starting with N";
    Image = "ImageName3.png";
    Text = "Some Text";
  },
  {
    Name = "N2...A Name Starting with N";
    Image = "ImageName4.png";
    Text = "Some Text";
  },
  {
    Name = "N3...A Name Starting with N";
    Image = "ImageName5.png";
    Text = "Some Text";
  }
  );
}

澄清一下,我在视图中安装了我的 searchBar,我只是无法使其正常工作。我目前正在使用书中示例中称为 - (void)handleSearchForTerm:(NSString *)searchTerm 的自定义方法。

感谢您的帮助!


这是数据的一般结构。

sectionedDictionaryByFirstLetter

Key   Value
B    Array of Dictionaries with Names beginning with B
      ....
C    Array of Dictionaries with Names beginning with C
      ...
N    Array of Dictionaries with Names beginning with N
     Item 1   Dictionary 1
     Item 2   Dictionary 2
     Item 3   Dictionary 3

          Dictionary 3
          {
          Name = "N3...A Name Starting with N";
          Image = "ImageName5.png";
          Text = "Some Text";
          }

我希望这会有所帮助。我仍在拼命寻找这个问题的答案。

本质上,有一个主字典,它的键是它包含的项目的第一个字母。在每个第一个字母中,都有一个字典数组,它们的“名称”键值以该字母开头。

【问题讨论】:

  • 查看我的答案,但您不想为此使用字典列表。你想创建一个 NSObject 子类,语法不会那么糟糕。

标签: iphone arrays dictionary filter


【解决方案1】:

你的数据结构搞砸了。

只需将要显示的所有字典组成一个数组,然后保持排序。将其分解为子字母只会使问题变得混乱。

所以,你会有一个这样的数组:

[[NSArray alloc] initWithObjects:
  [[NSDictionary alloc] initWithObjectsAndKeys: 
    @"a1", @"name", foo, @"bar", nil)],nil],
  [[NSDictionary alloc] initWithObjectsAndKeys: 
    @"b21", @"name", foo, @"bar", nil)],nil];

那么就很简单了。只需通过搜索栏中的输入过滤您的排序数组。您甚至可以将您的条目保存在 CoreData 数据库中,最后声明一个执行类似操作的函数来获取它们:

if (!self.wordList) {
  self.wordList = [self getWiordList]
} else {
  return self.wordList;
}

另外,我建议您创建一个 NSObject 子类,并使用它们的数组而不是字典,这样您就可以进行点访问并且语法很好。在 Obj C 中使用字典和列表并不像在 Python 中那样好。

继承一个 NSObject 很简单。

【讨论】:

  • 感谢您的回答。我使用分解为子字母的字典的原因是显示分段表视图。现在,表格显示精美,所有单元格都已排序,并且在正确的部分下,每个字母的标题以及部分索引。我不确定如何使用您建议的数据结构重新创建此设计。但是,我可以按照您推荐的过滤方式对其进行重组,然后将其更改回当前格式以显示数据。另外,我可能没有提到数据存储在 plist 中。
【解决方案2】:

更新

看起来您的数组中有由 Letter 键入的数组。

我可能会使用 NSPredicate 并过滤我感兴趣的任何键。

NSString *searchString = @"Nancy";

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(Name ==  %@)", Nancy];

NSArray *filteredArray = [[sectionedDictionaryByFirstLetter objectForKey:@"N"] filteredArrayUsingPredicate:predicate];

有一个关于谓词构造的指南。

还有其他方法,但这是首先想到的。


原答案

可以使用KVC方式:

valueForKeyPath:

得到你想要的。您应该阅读 KVC 苹果文档:

http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/

有很多方法可以“玩”字典/数组来做你想做的事。不同的技术会有不同的优势/优势。

【讨论】:

  • 您有更具体的想法吗?我正在花时间挖掘所有这些材料。谢谢!
  • 非常感谢您的帮助!这似乎是在正确的轨道上。但是,我想在每个首字母中进行搜索,而不仅仅是您示例中的“N”。我还希望首字母仅在包含项目时才保留在字典中。我编辑了问题以增加一点清晰度。
  • 您可以通过遍历键对每个字典执行上述搜索,然后聚合结果。但是,如果这些是您想要执行的搜索类型,我会考虑重组您的数据。为什么还要用首字母键入它们?如果需要,您始终可以搜索首字母,或者您可以将首字母设置为每个字典中的键值对。
【解决方案3】:

我的另一个想法是为“name”键创建一个包含所有值的数组。像这样的:

arrayOfNames:(
"B...A Name Starting with B",
"C...A Name Starting with C",
"N1...A Name Starting with N",
"N2...A Name Starting with N",
"N3...A Name Starting with N"
)

然后,在这个数组上运行过滤器。 最后,使用filteredArrayOfNames 将项目添加到具有匹配名称的新字典中。 从概念上讲,这似乎是在正确的轨道上吗?有更好的路线吗?

【讨论】:

    【解决方案4】:

    好的,我终于回答了我自己的问题。这是下面的代码。我主要按照“开始 iPhone 3 开发”中搜索数组的示例进行操作。我不得不稍微编辑它以使其适用于我的问题。这是我的代码:

    - (void)handleSearchForTerm:(NSString *)searchTerm
    {   
    NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
    [self resetSearch];
    for (NSString *key in self.keys)
    {
        NSMutableArray *array = [self.copyOfSectionedDictionaryByFirstLetter valueForKey:key];
        NSMutableArray *toRemove = [[NSMutableArray alloc] init];
        for (NSDictionary *name in array)
        {
            if ([[name objectForKey:@"Name"] rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound)
                [toRemove addObject:name];
        }
    
    if ([array count] == [toRemove count])
        [sectionsToRemove addObject:key];
    [array removeObjectsInArray:toRemove];
    [toRemove release];
    }
    
    [self.keys removeObjectsInArray:sectionsToRemove];
    [sectionsToRemove release];
    [self.tableView reloadData]; 
    }
    

    如果您想查看完整的示例代码以了解其工作原理,您可以从“开始 iPhone 3 开发”网站here 下载。这是“部分”示例。

    【讨论】:

      猜你喜欢
      • 2016-08-14
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 2017-03-27
      • 2021-08-24
      • 1970-01-01
      相关资源
      最近更新 更多