【问题标题】:Percent Similarity of an Array Swift数组 Swift 的相似度百分比
【发布时间】:2015-07-07 02:45:13
【问题描述】:

假设我有两个数组:

var arrayOne = ["Hi", "Hello", "Hey", "Howdy"]
var arrayOne = ["Hi", "Hello", "Hey", "Not Howdy"]

我可以做些什么来比较数组元素的相似程度?就像在返回 75% 的函数中一样,因为前三个元素相同,但最后一个元素不同。我在项目中使用的数组是字符串,但除了少数元素外,它们几乎完全匹配。我需要看看差异是多少百分比。有什么想法吗?

【问题讨论】:

标签: ios arrays swift


【解决方案1】:
let arrayOne = ["Hi", "Hello", "Hey", "Howdy"]
let arrayTwo = ["Hi", "Hello", "Hey", "Not Howdy"]
var matches = 0
for (index, item) in enumerate(arrayOne) {
    if item == arrayTwo[index] {
        matches++
    }
}
Double(matches) / Double(arrayOne.count)   // 0.75

【讨论】:

  • 如果你有 [1, 2, 3, 4] 和 [1, 1, 2, 3] 这样的代码,这个代码将不起作用,因为第二个 1 会以偏移量 1 抛出相似性。我回答中的第二个算法解决了这个问题(虽然可能不是最好的)。
【解决方案2】:

这两种算法都使用这样的想法,即如果您有两个不同长度的数组,您可以拥有的最高相似度是短长度/长长度,这意味着数组长度的差异被视为不匹配。

  1. 您可以将所有术语添加到一个集合中,然后将您的百分比设为集合的大小/最长数组的长度。

  2. 您可以对两个数组进行排序,然后使用每个数组的索引变量进行循环,并比较两个索引处的值,推进比较中具有“较低”值的数组的索引,或者如果它们相等,则增加一个计数器。您的百​​分比将是最长数组的计数器/长度。

但要考虑的一件事是,在奇怪的情况下如何衡量相似性。假设您有两个数组:[1, 2, 3, 4, 5] 和 [1, 1, 1, 1, 1]。我不知道您是否想说它们完全相似,因为第二个数组中的所有元素都在第一个数组中,或者它们是否只有 20% 的相似性,因为一旦第一个数组中的 1 是“用过”,不能再用了。

只是一些想法。

【讨论】:

    【解决方案3】:

    也许是这样的? (写在我的头上,所以没有检查它是否真的编译)

    var arrayOne = ["Hi", "Hello", "Hey", "Howdy"]
    var arrayTwo = ["Hi", "Hello", "Hey", "Not Howdy"]
    
    var matches = 0
    
    for i in 0...arrayOne.count { //assuming the arrays are always the same length
      if arrayOne[i] == arrayTwo[i]{
        matches++
      }
    }
    
    var percent = matches / arrayOne.count
    

    【讨论】:

      【解决方案4】:

      衡量2个数组相似度的一个好方法是迭代一个数组的所有元素,并在第2个数组上保持一个光标,这样在任何时候迭代数组的当前元素都不会大于所在的元素光标位置。

      您可能会争辩说,此算法要求元素具有可比性,因此如果数组类型实现了Comparable 接口,它就可以工作。

      我研究了一个执行该计算的通用函数,这里是:

      func compare<T: Comparable>(var lhs: [T], var rhs: [T]) -> (matches: Int, total: Int) {
          lhs.sort { $0 < $1 } // Inline sort
          rhs.sort { $0 < $1 } // Inline sort
      
          var matches = 0
          var rightSequence = SequenceOf(rhs).generate()
          var right = rightSequence.next()
      
          for left in lhs {
              while right != nil && left > right {
                  right = rightSequence.next()
              }
      
              if left == right {
                  ++matches
                  right = rightSequence.next()
              }
          }
      
          return (matches: matches, total: max(lhs.count, rhs.count))
      }
      

      让我说实现可能可以优化,但我在这里的目标是展示算法,而不是提供最佳实现。

      要做的第一件事是获取 2 个数组中每一个的排序版本 - 为简单起见,我将两个参数声明为 var,这允许我编辑它们,将所有更改保留在本地范围内。这就是我使用就地排序的方式。

      在第二个数组上创建一个序列,称为rightSequence,并提取第一个元素,复制到right 变量中。

      然后迭代第一个数组 - 对于每个元素,序列前进到下一个元素,直到左侧元素不大于右侧元素。

      完成此操作后,将比较左右是否相等,在这种情况下,匹配计数器会递增。

      该算法适用于具有重复、不同大小等的数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-10
        • 1970-01-01
        • 2016-09-07
        • 2012-04-07
        • 2013-02-01
        • 2018-03-08
        • 2019-01-06
        • 2021-01-14
        相关资源
        最近更新 更多