2012-03-09 25 views
5

Tôi có một loại từ điển không thân thiện với các từ điển mà lần lượt có mảng dữ liệu và tôi đang cố gắng lọc mảng ngoài dựa trên bất kỳ mảng trong nào đi qua một vị từ. Tôi không thể tạo ra một NSPredicate để thực hiện công việc này. Tôi bắt đầu với:NSPredicate subquery syntax

NSPredicate *lookupPredicate = [NSPredicate predicateWithFormat: 
      @"row_values.property_id == %@ AND row_values.property_value == %@", 
       @"47cc67093475061e01000540", @"Male"]; 

[dataRows filterUsingPredicate:lookupPredicate]; 

Điều này sẽ không trả về giá trị. Tôi đã thử các hình thức khác nhau của BẤT K but nhưng tôi dường như không thể tìm thấy bất cứ điều gì mà nó sẽ phân tích cú pháp. Một lần nữa, mục tiêu là chỉ giữ các từ điển mảng bên ngoài, nơi vị từ cho bất kỳ nội dung từ điển mảng bên trong nào là đúng. Tôi có thể thấy tôi nhai một ngày để tìm ra câu thần chú để thực hiện công việc này ... bất kỳ ý tưởng nào?

dataRows: 
(
{ 
    row = 1; 
    "row_values" =  (
      { 
       "property_id" = 47cc67093475061e01000542; 
       "property_value" = "Mr."; 
      }, 
      { 
       "property_id" = 47cc67093475061e01000540; 
       "property_value" = Male; 
      } 
    ); 
}, 
{ 
    row = 2; 
    "row_values" =  (
      { 
      "property_id" = 47cc67093475061e01000542; 
      "property_value" = "Ms."; 
      }, 
... 
    } 
} 
+0

Có thể trùng lặp [Nơi tìm tài liệu về tính năng SUBQUERY của NSPredicate cho dữ liệu lõi?] (Http://stackoverflow.com/questions/3076618/where-to-find-the-documentation-of-the- subquery-feature-of-nspredicate-for-core) – Senseful

Trả lời

21

Người đàn ông, "không thân thiện" là cách nói ngắn gọn về mảng đó!

OK, tôi nghĩ rằng tôi figured này ra:

NSArray *dataRows = @[ 
         @{ @"row" : @"1", 
         @"row_values" : @[ 
              @{ @"property_id" : @"47cc67093475061e01000542", 
               @"property_value" : @"Mr." }, 
              @{ @"property_id" : @"47cc67093475061e01000540", 
               @"property_value" : @"Male" } 
              ] 
         }, 
         @{ @"row" : @"2", 
         @"row_values" : @[ 
              @{ @"property_id" : @"47cc67093475061e01000542", 
               @"property_value" : @"Ms." }, 
              @{ @"property_id" : @"47cc67093475061e01000540", 
               @"property_value" : @"Female" } 
              ] 
         } 
        ]; 

NSPredicate *p = [NSPredicate predicateWithFormat:@"SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@)[email protected] > 0", @"47cc67093475061e01000540", @"Male"]; 

NSArray *filtered = [dataRows filteredArrayUsingPredicate:p]; 

Vì vậy, chúng ta hãy xem những gì vị này đang làm.

  1. Bắt đầu với bên ngoài-nhất cấp:

    SUBQUERY([stuff])[email protected] > 0 
    

    Một SUBQUERY trả về một mảng các đối tượng. Chúng tôi sẽ chạy điều này SUBQUERY trên mỗi NSDictionary trong mảng dataRows và chúng tôi muốn tổng hợp tất cả các từ điển mà từ đó SUBQUERY trên từ điển đó trả lại một cái gì đó. Vì vậy, chúng tôi chạy các SUBQUERY, và sau đó (kể từ khi nó trả về một bộ sưu tập), yêu cầu nó bao nhiêu mục trong đó ([email protected]) và xem nếu đó là lớn hơn 0. Nếu có, thì từ điển cấp cao nhất sẽ ở trong mảng lọc cuối cùng.

  2. Dig vào SUBQUERY:

    SUBQUERY(row_values, $rv, $rv.property_id = %@ AND $rv.property_value = %@) 
    

    Có ba thông số cho mọi SUBQUERY: Một con đường chính, một biến, và một vị. Đường dẫn chính là thuộc tính của đối tượng mà chúng ta sẽ lặp lại. Vì SUBQUERY đang được đánh giá trên các từ điển ngoài cùng, chúng tôi sẽ yêu cầu @"row_values" từ điển đó và lấy lại một mảng. Sau đó, SUBQUERY sẽ lặp qua các mục trong bộ sưu tập row_values.

    Biến là những gì chúng tôi sẽ gọi mỗi mục trong bộ sưu tập. Trong trường hợp này, nó chỉ đơn giản là là $rv (viết tắt của "giá trị hàng"). Trong trường hợp của chúng tôi, mỗi $rv sẽ là NSDictionary, vì thuộc tính "row_values" là một bộ từ điển.

    Cuối cùng, biến vị ngữ sẽ được thực hiện, với lần lượt $rv được thay thế cho mỗi từ điển. Trong trường hợp này, chúng tôi muốn xem từ điển có một số property_id và một số property_value nhất định không. Nếu nó, nó sẽ được tổng hợp thành một mảng mới, và đó là mảng sẽ được trả lại từ SUBQUERY.

    Vì vậy, để nói theo cách khác, SUBQUERY sắp xây dựng một mảng của tất cả các giá trị hàng có một property_idproperty_value về những gì chúng tôi đang tìm kiếm.

Và cuối cùng, khi tôi chạy mã này, tôi nhận được:

(
     { 
     row = 1; 
     "row_values" =   (
         { 
       "property_id" = 47cc67093475061e01000542; 
       "property_value" = "Mr."; 
      }, 
         { 
       "property_id" = 47cc67093475061e01000540; 
       "property_value" = Male; 
      } 
     ); 
    } 
) 
+1

Thực ra tôi chỉ đơn giản hóa cấu trúc nguồn để tôi có thể sử dụng một biến vị ngữ dễ dàng hơn nhiều. Joking ... cảm ơn rất nhiều Dave !! Điều này làm việc hoàn hảo và nó có ý nghĩa. Tôi thực sự đánh giá cao sự giúp đỡ và cho tôi biết nếu bạn cần trợ giúp về một cái gì đó như giá trị RGB cho màu đen hoặc có bao nhiêu nguyên âm bằng tiếng Anh - những thứ tôi có thể xử lý. – michael

+1

Bạn thật tuyệt vời, cảm ơn Dave! – flypig

0

tài liệu subquery của Apple đang rải rác khắp nhiều nơi.

Định dạng chuỗi cho một biểu thức subquery là:

SUBQUERY(collection_expression, variable_expression, predicate);

nơi biểu thức là một biểu thức vị ngữ để đánh giá một tập hợp, biếnExpression là một biểu thức sẽ được sử dụng để chứa mỗi cá thể al phần tử của bộ sưu tập và vị từ là vị từ được sử dụng để xác định xem phần tử đó có nằm trong tập hợp kết quả hay không.

Để biết thêm chi tiết và ví dụ, hãy xem my answer to a similar question about the documentation for SUBQUERY syntax.