【问题标题】:How to get the Lowest and Highest Value from Dictionary in Swift如何在 Swift 中从字典中获取最低和最高值
【发布时间】:2019-04-23 18:32:41
【问题描述】:

我在获取值以进行所需组合时遇到问题。我在我的应用程序中使用过滤器屏幕。我问这个问题是为了从问题How to put the of first and last element of Array in Swift 中获取第一个和最后一个元素,它正在工作,但问题出在我的FiterVC 中,首先我选择了选项$400 - $600,然后我选择了$200 - $400。选择后,我在 currentFilter 变量中获取这些值。

private let menus = [

    ["title": "Price", "isMultiSelection": true, "values": [
        ["title": "$00.00 - $200.00"],
        ["title": "$200.00 - $400.00"],
        ["title": "$400.00 - $600.00"],
        ["title": "$600.00 - $800.00"],
        ["title": "$800.00 - $1000.00"],
        ]],
    ["title": "Product Rating", "isMultiSelection": true, "values": [
        ["title": "5"],
        ["title": "4"],
        ["title": "3"],
        ["title": "2"],
        ["title": "1"]
        ]],
    ["title": "Arriving", "isMultiSelection": true, "values": [
        ["title": "New Arrivials"],
        ["title": "Coming Soon"]
        ]]
]

private var currentFilters = [String:Any]()

didSelect方法中选择值:-

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if tableView === self.menuTableView {
        self.currentSelectedMenu = indexPath.row
        self.menuTableView.reloadData()
        self.valueTableView.reloadData()
    }
    else {
        if let title = self.menus[self.currentSelectedMenu]["title"] as? String, let values = self.menus[self.currentSelectedMenu]["values"] as? [[String:Any]], let obj = values[indexPath.row]["title"] as? String {
            if let old = self.selectedFilters[title] as? [String], let isAllowedMulti = self.menus[self.currentSelectedMenu]["isMultiSelection"] as? Bool, !old.isEmpty, !isAllowedMulti {
                var temp = old
                if old.contains(obj), let index = old.index(of: obj) {
                    temp.remove(at: index)
                }
                else {
                    temp.append(obj)     
                }
                self.selectedFilters[title] = temp
            }
            else {
                self.selectedFilters[title] = [obj]
            }
            self.valueTableView.reloadData()
        }
    }
}

然后点击应用按钮:-

@IBAction func applyButtonAction(_ sender: UIButton) {
    self.delegate?.didSelectedFilters(self, with: self.selectedFilters)
    printD(self.selectedFilters)
    self.dismiss(animated: true, completion: nil)
}

当我打印 selectedFilters 时,我得到了这些值:-

currentFilters ["Price": ["$400.00 - $600.00", "$200.00 - $400.00"]]

通过使用这种方法,我可以从字典中获取第一个和最后一个值,如下所示:-

if let obj = currentFilters["Price"] as? [String] {
   self.priceRange = obj
   printD(self.priceRange)

   let first = priceRange.first!.split(separator: "-").first!
   let last = priceRange.last!.split(separator: "-").last!
   let str = "\(first)-\(last)"
   let str2 = str.replacingOccurrences(of: "$", with: "", options: NSString.CompareOptions.literal, range: nil)
   newPrice = str2
   printD(newPrice)
}

结果是:-

400.00 - 400.00

但我真正想要的是200 - 600。我怎样才能做到这一点。请帮忙?

【问题讨论】:

  • 用“-”分割数组后,检查是否选择了正确的数组项。 priceRange.first!.split(separator: "-") 和 priceRange.last!.split(separator: "-") 中有哪些项目?
  • @wings 它不起作用,因为您不是在寻找最大的价值,而是在寻找第一个和最后一个元素。这些方法不知道里面包含的值。
  • 为什么不使用映射表,例如0 = 0-200, 1 = 200-400 等?下限值始终为x * 200,上限值始终为x * 200 + 200?这避免了使用 splitreplaceOccurrences 进行烦人的提取
  • 为按钮分配标签 (0-5)。将 currentFilters 声明为整数 array var currentFilters = [Int]()。选择/取消选择过滤器时,将标签添加/从数组中添加/删除。如前所述,较低的值为tag * 200,较高的值为tag * 200 + 200
  • 你可以。这是设计的问题。我只是提出了一个建议,以改进一个非常繁琐且效率低下的设计。

标签: ios arrays swift dictionary swift4


【解决方案1】:

我们可以按部就班-

1 - 从字典中获取价格范围

2 - 遍历这些价格范围

3 - 用“-”分割范围并检查价格计数是否为 2,否则这是无效的价格范围

4 - 从两个价格中获取数值成分,然后与之前保存的最小值和最大值进行比较并相应地更新它们

试试这个 -

if let priceRanges = currentFilters["Price"] as? [String] { // Extract the price ranges from dictionary

    var minValue: Double? // Holds the min value
    var maxValue: Double? // Holds the max value

    for priceRange in priceRanges { Iterate over the price ranges

        let prices = priceRange.split(separator: "-") // Separate price range by "-"

        guard prices.count == 2 else { // Checks if there are 2 prices else price range is invalid
            print("invalid price range")
            continue // skip this price range when invalid
        }

        let firstPrice = String(prices[0]).numericString // Extract numerics from the first price
        let secondPrice = String(prices[1]).numericString // Same for the second price

        if let value = Double(firstPrice) { // Check if the price is valid amount by casting it to double
            if let mValue = minValue { // Check if we have earlier saved a minValue from a price range
                minValue = min(mValue, value) // Assign minimum of current price and earlier save min price
            } else {
                minValue = value // Else just save this price to minValue
            }
        }

        if let value = Double(secondPrice) { // Check if the price is valid amount by casting it to double
            if let mValue = maxValue { // Check if we have earlier saved a maxValue from a price range
                maxValue = max(mValue, value) // Assign maximum of current price and earlier save max price
            } else {
                maxValue = value // Else just save this price to maxValue
            }
        }
    }
    if let minV = minValue, let maxV = maxValue { // Check if we have a min and max value from the price ranges
        print("\(minV) - \(maxV)")
    } else {
        print("unable to find desired price range") // Else print this error message
    }
}

extension String {

    /// Returns a string with all non-numeric characters removed
    public var numericString: String {
        let characterSet = CharacterSet(charactersIn: "01234567890.").inverted
        return components(separatedBy: characterSet)
            .joined()
    }
}

【讨论】:

  • 请先生解释一下您的答案
  • @wings 我已经更新了答案,如果您需要更多信息,请告诉我
  • 好的,我现在去看看
【解决方案2】:

这是您的问题的小解决方案。这一切都分解为:您从过滤器中获取所有值,然后迭代从中获取所有值。这样您就可以避免比较这些对,而是比较确切的值。

let currentFilters =  ["Price": ["$400.00 - $600.00", "$200.00 - $400.00"]]
let ranges = currentFilters["Price"]!
var values: [Double] = []
ranges.forEach { range in // iterate over each range
    let rangeValues = range.split(separator: "-")
    for value in rangeValues { // iterate over each value in range
        values.append(Double( // cast string value to Double
            String(value)
                .replacingOccurrences(of: " ", with: "")
                .replacingOccurrences(of: "$", with: "")
        )!)
    }
}

let min = values.min() // prints 200
let max = values.max() // prints 600

【讨论】:

  • 这行不通,通过比较字符串值意味着 $1000.00 将小于 $400.00。
  • @inokey 请不要强制解包,这会导致在某些情况下崩溃
【解决方案3】:

然而,有很多解决方案可以解决这个问题,但这里重点介绍了最简单和最相关的解决方案:

let min = 1000, max = 0
if let obj = currentFilters["Price"] as? [String] {
   self.priceRange = obj
   printD(self.priceRange)

   for str in obj{
     let first = str.split(separator: "-").first!.replacingOccurrences(of: "$", with: "", options:
            NSString.CompareOptions.literal, range: nil)
     let last = str.split(separator: "-").last!.replacingOccurrences(of: "$", with: "", options:
            NSString.CompareOptions.literal, range: nil)
     if Int(first) < min{
       min = first
     }
     if Int(last) > max{
       max = last
     }
   }
   let str = "\(min)-\(max)"
   newPrice = str
   printD(newPrice)
}

【讨论】:

  • 这是错误的。您的 minInt 声明,您的编译器将在 if 语句行抛出错误。
  • 价格是Double,而不是Int
  • @inokey : 改为 Double 类型
【解决方案4】:

您可以使用带有函数的枚举来加载您的价格范围,而不是直接使用字符串。

enum PriceRange: String {
    case
    low     = "200 - 400",
    high    = "400 - 600"

    static let priceRanges = [low, high]

    func getStringValue() -> String {
        return self.rawValue
    }

    func getMinValueForRange(stringRange: String) -> Int? {
        switch stringRange {
        case "200 - 400":
            return 200;

        case "400 - 600":
            return 400;
        default:
            return nil
        }
    }

    func getMaxValueForRange(stringRange: String) -> Int? {
        switch stringRange {
        case "200 - 400":
            return 400;

        case "400 - 600":
            return 600;
        default:
            return nil
        }
    }

}

然后您可以使用/添加函数来获得您正在寻找的结果。

【讨论】:

  • 价格范围是动态的,可能不是 200 的倍数
猜你喜欢
  • 2023-01-10
  • 2018-12-21
  • 1970-01-01
  • 2017-09-19
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多