0

On print po menuList?[1]["subMenu"]

I got below message

▿ Optional<Any>
  ▿ some : 1 element
    ▿ 0 : 1 element
      ▿ 0 : 2 elements
        - key : subItem
        ▿ value : 4 elements
          ▿ 0 : 7 elements
            ▿ 0 : 2 elements
              - key : permission
              - value : access
            ▿ 1 : 2 elements
              - key : title
              - value : Create
            ▿ 2 : 2 elements
              - key : bar
              - value : sidebar
            ▿ 3 : 2 elements
              - key : isNotify
              - value : 0
            ▿ 4 : 2 elements
              - key : link
              - value : linker
            ▿ 5 : 2 elements
              - key : path
              - value : /dashboard
            ▿ 6 : 2 elements
              - key : icon
              - value : add

Trying to extract menuList?[i]["subMenu"]["subItem"] based on condition if value exist in side subItem then append to array else not.

few cases ["subItem"] may have 0 elements

    if let permissionList =  MenuList?[i]["subMenu"] {
        let subMenu =  (permissionList as AnyObject)
        if subMenu.count > 0 {
            for j in 0..<subMenu.count{
             let subItem =  subMenu["subItem"]
            }
        }

Its return nil for me

On try subMenu[0] error: ambiguous use of 'subscript(_:)' subMenu[0]

8
  • What have you tried? How was the result different than what you expected? Commented Aug 3, 2021 at 1:16
  • @jnpdx I updated question what i have tried. Commented Aug 3, 2021 at 1:25
  • In your sample data you printed, subItem only appears after two levels of arrays. Right now, it looks like you're just one level deep. Commented Aug 3, 2021 at 1:29
  • @kiran What's the type of menuList? It would help to figure this out. Commented Aug 3, 2021 at 1:46
  • @George_E var menuList: [[String: Any]]? its array of dictionary Commented Aug 3, 2021 at 1:47

2 Answers 2

1

Here's a variant of George's function, expressing using a map operation rather than a hand-rolled loop:

func menuResult() -> [String] {
    // FIXME: Why is this even optional in the first place?
    guard let menuList = menuList else { return [] }

    return menuList.compactMap { menu -> [String] in
        guard let subMenu = menu["subMenu"] as? [String: String] else { return nil }
        return subMenu["subItem"]
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

or simply (menu["subMenu"] as? [String: String])?["subItem"]. Single line is also preferred as it benefits type inference. Not sure but menuList?.compactMap { ($0["subMenu"] as? [String: String])?["subItem"] } ?? [] should work
@LeoDabus Yep, though I avoided going that far because debugging that was really a pain. Maybe now that Xcode lets you place breakpoints within expressions, expressions like this might be more reasonable to work with
0

For example menuData like this:

let menuList: [[String: Any]]? = [
    ["abc": [
        "123": "test1",
        "456": "test2"
    ]],
    ["def": [
        "789": "test3",
        "101112": "test4"
    ]],
    ["subMenu": [
        "subItem": "Other correct path" // <- subMenu[2]["subMenu"]["subItem"]
    ]],
    ["subMenu": [
        "otherItem": "WRONG",
        "subItem": "CORRECT" // <- subMenu[3]["subMenu"]["subItem"]
    ]]
]

Code to get all items in the menuData array at menuData[i]["subMenu"]["subItem"]:

func menuResult() -> [String] {
    // menuList can't start nil
    guard let menuList = menuList else { return [] }
    var result = [String]()

    // Iterate every element of menuList
    for i in menuList.indices {
        // Get 'subMenu' dictionary if it exists
        if let subMenu = menuList[i]["subMenu"] as? [String: String] {
            // Get 'subItem' dictionary if it exists
            if let subItem = subMenu["subItem"] {
                // Store value at this path
                result.append(subItem)
            }
        }
    }

    return result
}
print(menuResult())
// Prints: ["Other correct path", "CORRECT"]

8 Comments

Your for loop can be replaced with a simple compactMap.
Might I also suggest removing comment like // Return result when the code literally says return result. There should be a really high bar for what gets commented.
I have some tips/tricks that might benefit this code, if you're interested. Would be easier to discuss them in SE chat, though
@Alexander Tbh, I think I just got a little bit carried away with the comments here 😅 Looking back it definitely has got quite a few inefficiencies (such as the index, not really neededP
I don't use twitter, but I'd be happy to chat here. A chatroom link should be offered if we spam comments back and forth a few more times
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.