【问题标题】:Counting number of Arrays that contain the same two values计算包含相同两个值的数组的数量
【发布时间】:2014-10-21 16:05:15
【问题描述】:

给定一个Dictionary<String, Arrary<Int>>,在Array<Int> 的第一个5 条目中找出有多少条目具有相同的两个指定值。

例如:

给定:

let numberSeries = [

    "20022016": [07,14,36,47,50,02,05],
    "13022016": [16,07,32,36,41,07,09],
    "27022016": [14,18,19,31,36,04,05],

]

值:736,结果应该是 2,因为第一个和第二个条目在条目数组的前 5 个条目中同时具有值​​ 736

我尝试了很多方法来完成这件事,但我无法让它发挥作用。

这是我目前的尝试:

//created a dictionary with (key, values)

let numberSeries = [

"20022016": [07,14,36,47,50,02,05],
"13022016": [16,07,32,36,41,07,09],
"27022016": [14,18,19,31,36,04,05],

]

var a = 07  //number to look for
var b = 36  // number to look for

// SearchForPairAB // search for pair // Doesn't Work.                                  

var ab = [a,b] // pair to look for
var abPairApearedCount = 0

for (kind, numbers) in numberSeries {
    for number in numbers[0...4] {
         if number == ab {           //err: Cannot invoke '==' with argument listof type Int, @Value [Int]
             abPairApearedCount++
         }
     }
 }

这给出了错误:Cannot invoke '==' with argument listof type Int, @Value [Int]就行了:if number == ab

【问题讨论】:

  • 对我的意思是值“a”和值“b”在同一个数组、行、前 5 个位置(这就是我使用 [0...4] 的原因)。我把代码分成三部分,前两部分在数组中寻找单个数字,最后一个在同一个数组中寻找两个数字,不知道怎么写。我尝试了不同的东西,但没有做对。我需要它来输出答案“2”,因为数字“a”和“b”一起出现在两条不同的行中。希望这能带来一些启发......
  • 好吧,正如@MikeS 所说,目前尚不清楚您要实现什么,但错误很简单 - ab 是一个 Ints 数组,number 是一个 Int。它们没有可比性。
  • 认为我发送了我过去的评论,就像您发送您的评论一样。希望很清楚,我不想比较这两个值。我想知道它们在同一个数组中出现了多少次。该示例显示了三个数组,但我有数千个。
  • @Francisco 我编辑了你的问题,试图根据你的 cmets 在这里澄清它。如果我遗漏了什么或者我弄错了,请告诉我,我会回滚编辑。

标签: ios arrays dictionary swift


【解决方案1】:

您不能使用== 来比较IntArray<Int>,从比较的角度来看这没有任何意义。不过,有很多不同的方法可以实现你想要做的事情。在这种情况下,我可能会使用map/reduce 来计算您的配对。

这个想法是将mapab 数组中的值转换为Bool 值,这取决于该值是否在numbers 数组中。然后,reduceBools 映射到单个值:true,如果它们都是true,或false。如果 reduced 的值是 true,那么我们找到了这对,所以我们增加了计数。

var ab = [a,b] // pair to look for
var abPairApearedCount = 0

for (kind, numbers) in numberSeries {
    let found = ab.map({ number in
        // find is a built-in function that returns the index of the value
        // in the array, or nil if it's not found
        return find(numbers[0...4], number) != nil
    }).reduce(true) { (result, value: Bool) in
        return result && value
    }
    if found {
        abPairApearedCount++
    }
}

这实际上可以通过使用一些 Swift 更简洁的语法来压缩:

var ab = [a,b] // pair to look for
var abPairApearedCount = 0

for (kind, numbers) in numberSeries {
    let found = ab.map({ find(numbers[0...4], $0) != nil }).reduce(true) { $0 && $1 }
    if found {
        abPairApearedCount++
    }
}

而且,为了好玩,可以通过使用reduce 而不是for-in 循环进一步压缩:

var ab = [a,b] // pair to look for
var abPairApearedCount = reduce(numberSeries, 0) { result, series in
    result + (ab.map({ find(series.1[0...4], $0) != nil }).reduce(true) { $0 && $1 } ? 1 : 0)
}

虽然这变得相当难以理解,所以我可能会扩展其中的一些内容。

【讨论】:

  • 如果你想进一步编码高尔夫,你可以去掉map并将其与内部reduce合并。
【解决方案2】:

这是我的 FP 解决方案,旨在将问题分解为易于消化和可重复使用的小块:

首先,我们定义一个将数组修剪为给定长度的函子:

func trimLength<T>(length: Int) -> ([T]) -> [T] {
    return { return Array($0[0...length]) }
}

使用这个我们可以使用map(array, trimLength(5))修剪所有元素

现在,我们需要一个谓词来确定一个数组的所有元素是否都在目标数组中:

func containsAll<T:Equatable>(check:[T]) -> ([T]) -> Bool {
    return { target in
        return reduce(check, true, { acc, elem in return acc && contains(target, elem) })
    }
}

这是这里最难看的代码,但本质上它只是迭代检查并确保每个元素都在目标数组中。一旦我们得到这个,我们就可以使用filter(array, containsAll([7, 26])) 来消除数组中不包含我们所有目标值的所有元素。

此时,我们可以将整个事情粘合在一起:

filter(map(numberSeries.values, trimLength(5)), containsAll([7, 36])).count

但是长行的嵌套函数很难阅读,让我们定义几个辅助函数和一个自定义运算符:

func rmap<S:SequenceType, T>(transform:(S.Generator.Element)->T) -> (S) -> [T] {
    return { return map($0, transform) }
}

func rfilter<S:SequenceType>(predicate:(S.Generator.Element)->Bool) -> (S) -> [S.Generator.Element] {
    return { sequence in return filter(sequence, predicate) }
}

infix operator <^> { associativity left }
func <^> <S, T>(left:S, right:(S)->T) -> T {
    return right(left)
}

还有一个方便的函数来计算它的输入:

func count<T>(array:[T]) -> Int {
    return array.count
}

现在我们可以将整个事情浓缩为:

numberSeries.values <^> rmap(trimLength(5)) <^> rfilter(containsAll([7, 36])) <^> count

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2017-12-28
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多