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

时间:2018-11-21 08:22:58

标签: ios arrays swift dictionary swift4

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

$200 - $400

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

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

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

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

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 。我怎样才能做到这一点。请帮忙吗?

5 个答案:

答案 0 :(得分:0)

我认为您应该将所有相关的过滤信息存储在单独的类中。一旦以字符串形式获取它们,就应该将它们更改为适当的结构化数据。 (如果您是自己创建它们,则无论出于任何原因都不应将它们作为字符串使用)

class PriceRange {
    var minValue: Int
    var maxValue: Int

    init(_ minValue: Int, _ maxValue: Int) {
        self.minValue = minValue
        self.maxValue = maxValue
    }
}

class ProductRating { // Relevant naming
    // Relevant parameters
}

class Arriving { // Relevant naming
    // Relevant parameters
}

// The class whose object which store the filtered information
class Filters {
    var priceRange: [PriceRange]
    var productRating: [ProductRating] // Change as necessary
    var arriving: [Arriving] // Change as necessary

    init(priceRange: [PriceRange], productRating: [ProductRating], arriving: [Arriving]) {
        self.priceRange = priceRange
        self.productRating = productRating
        self.arriving = arriving
    }
}

现在,如果您设法获取过滤器,则通过过滤默认的一组过滤器数组来应用。你会有类似的东西。

var filteredPriceRanges = [PriceRange(400, 600), PriceRange(200, 400)] // Example
var filtersApplied = Filters(priceRange: filteredPriceRanges, productRating: /* filtered product rating */, arriving: /* filtered arriving information */)
let selectedRanges = filtersApplied.priceRange

现在您要做的就是将其减小到最小和最大范围。

let finalRange = selectedRanges.reduce(PriceRange(selectedRanges.first?.minValue ?? 0, selectedRanges.first?.maxValue ?? 0)) { (result, range) -> PriceRange in
    if result.minValue > range.minValue {
        result.minValue = range.minValue
    }
    if result.maxValue < range.maxValue {
        result.maxValue = range.maxValue
    }
    return result
}

// Note this returns (0, 0) if none of the filters are selected. So make sure you have some way of enforcing the use has atleast one filter selected

答案 1 :(得分:0)

但是,有很多解决方案可以解决此问题,但是最简单,最相关的解决方案在此处突出显示:

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

答案 2 :(得分:-1)

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

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

}

然后,您可以使用/添加函数以获取所需的结果。

答案 3 :(得分:-2)

我们可以按部就班-

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

答案 4 :(得分:-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