简体   繁体   English

如何在Swift中从字典中获得最低和最高价值

[英]How to get the Lowest and Highest Value from Dictionary in Swift

I am facing a problem in getting the values to make the desired combination. 我在获取值以进行所需组合时遇到问题。 I am using a filter screen in my app. 我在应用程序中使用了过滤器屏幕。 I asked this question to get the first and last element from the question How to put the of first and last element of Array in Swift and it is working but the problem is in my FiterVC first I selected the option $400 - $600 and then I selected the $200 - $400 . 我问了这个问题,从问题中获取第一个和最后一个元素。 如何将数组的第一个和最后一个元素放入Swift中 ,它正在工作,但问题出在我的FiterVC中,我首先选择了$400 - $600选项,然后选择了$200 - $400 After selecting I am getting these values in my currentFilter variable. 选择后,我将在我的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]()

Selecting values in didSelect method:- 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()
        }
    }
}

And on Apply button click:- 然后在“应用”按钮上单击:-

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

When I am printing the selectedFilters I am getting these values:- 当我打印selectedFilters时,我得到了这些值:

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

And by using this method I am getting the first and last value from dictionary like this:- 通过使用这种方法,我可以从字典中获取第一个和最后一个值,如下所示:

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)
}

The result is :- 其结果是:-

400.00 - 400.00

but what I actually want is 200 - 600 . 但是我真正想要的是200 - 600 How can I do this. 我怎样才能做到这一点。 Please help? 请帮忙?

However there are many solutions available to this problem but simplest and most relevant solution is highlighted here: 但是,有许多解决方案可用于解决此问题,但此处重点介绍了最简单,最相关的解决方案:

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)
}

You can use an enum with functions to load your prices ranges instead of using directly Strings. 您可以使用带有函数的枚举来加载价格范围,而不是直接使用字符串。

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
        }
    }

}

Then you can use/add functions to get the result that you are looking for. 然后,您可以使用/添加函数以获取所需的结果。

We can do by steps - 我们可以循序渐进-

1 - Get the price ranges from the dictionary 1-从字典中获取价格范围

2 - Iterate over those price ranges 2-遍历这些价格范围

3 - Split the range by "-" and check if the prices count is 2 else this is an invalid price range 3-用“-”分隔范围,然后检查价格计数是否为2,否则这是无效的价格范围

4 - Get the numeric components from the two prices and then compare from the previously saved min and max values and update them accordingly 4-从两个价格中获取数字成分,然后与之前保存的最小和最大值进行比较,并进行相应的更新

Try this - 尝试这个 -

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()
    }
}

Here's the small solution of your problem. 这是您的问题的小解决方案。 It all breaks down to that: you get all the values from your filters, and then iterating over getting all the values from it. 一切都分解为:您从过滤器中获取所有值,然后进行迭代以从中获取所有值。 That way you avoid comparing the pairs and instead comparing the exact values. 这样,您就可以避免比较这些对,而不必比较确切的值。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM