【问题标题】:Most common array elements最常见的数组元素
【发布时间】:2015-02-21 02:05:02
【问题描述】:

我需要在数组中找到最常见的(模态)元素。

我能想到的最简单的方法是为每个唯一元素设置变量,并为每个元素分配一个计数变量,每次记录在遍历数组的 for 循环中时,计数变量都会增加。

可惜数组的大小是未知的,会很大,所以这个方法没用。

我在 Objective-C 中遇到过一个类似的问题,它使用 NSCountedSet 方法对数组元素进行排名。不幸的是,我对编程很陌生,只能将第一行翻译成 Swift。

建议的方法如下:

    var yourArray: NSArray! // My swift translation

    NSCountedSet *set = [[NSCountedSet alloc] initWithArray:yourArray];

    NSMutableDictionary *dict=[NSMutableDictionary new];

    for (id obj in set) {
        [dict setObject:[NSNumber numberWithInteger:[set countForObject:obj]]
            forKey:obj]; //key is date
    }

    NSLog(@"Dict : %@", dict);

    NSMutableArray *top3=[[NSMutableArray alloc]initWithCapacity:3];

    //which dict obj is = max
    if (dict.count>=3) {

        while (top3.count<3) {
            NSInteger max = [[[dict allValues] valueForKeyPath:@"@max.intValue"] intValue];

            for (id obj in set) {
                if (max == [dict[obj] integerValue]) {
                    NSLog(@"--> %@",obj);
                    [top3 addObject:obj];
                    [dict removeObjectForKey:obj];
                }
            }
        }
    }

    NSLog(@"top 3 = %@", top3);

在我的程序中,我需要在一个数组中查找前五个地名。

【问题讨论】:

  • “前 5 名”是什么意思。您的数组是否多次包含相同的元素?你想知道哪些是最顶级的吗?
  • 该数组将包含一个城市名称列表,用户签到的地方。我需要对数组中的元素进行排序,以输出用户签到次数最多的五个地方.所以是的,数组中的元素会重复多次

标签: arrays swift nscountedset


【解决方案1】:

编辑:现在使用以下 Swift 2.0

不是最有效的解决方案,而是一个简单的解决方案:

let a = [1,1,2,3,1,7,4,6,7,2]

var frequency: [Int:Int] = [:]

for x in a {
    // set frequency to the current count of this element + 1
    frequency[x] = (frequency[x] ?? 0) + 1
}

let descending = sorted(frequency) { $0.1 > $1.1 }

descending 现在由一对数组组成:值和频率, 首先排序最频繁。所以“前 5 个”将是前 5 个条目 (假设有 5 个或更多不同的值)。源数组有多大并不重要。

这是一个适用于任何序列的通用函数版本:

func frequencies
  <S: SequenceType where S.Generator.Element: Hashable>
  (source: S) -> [(S.Generator.Element,Int)] {

    var frequency: [S.Generator.Element:Int] = [:]

    for x in source {
        frequency[x] = (frequency[x] ?? 0) + 1
    }

    return sorted(frequency) { $0.1 > $1.1 }
}

frequencies(a)

对于 Swift 2.0,您可以将该函数改编为协议扩展:

extension SequenceType where Generator.Element: Hashable {
    func frequencies() -> [(Generator.Element,Int)] {

        var frequency: [Generator.Element:Int] = [:]

        for x in self {
            frequency[x] = (frequency[x] ?? 0) + 1
        }

        return frequency.sort { $0.1 > $1.1 }
    }
}

a.frequencies()

对于 Swift 3.0:

extension Sequence where Self.Iterator.Element: Hashable {
    func frequencies() -> [(Self.Iterator.Element,Int)] {

        var frequency: [Self.Iterator.Element:Int] = [:]

        for x in self {
            frequency[x] = (frequency[x] ?? 0) + 1
        }

        return frequency.sorted { $0.1 > $1.1 }
    }
}

【讨论】:

  • 请注意,您的 if-let-else 可以简化为 frequency[x] = 1 + (frequency[x] ?? 0)
  • Swift 3 的语法是什么?
【解决方案2】:

对于 XCode 7.1,解决方案是。

// Array of elements
let a = [7,3,2,1,4,6,8,9,5,3,0,7,2,7]

// Create a key for elements and their frequency
var times: [Int: Int] = [:]

// Iterate over the dictionary
for b in a {
    // Every time there is a repeat value add one to that key
    times[b] = (times[b] ?? 0) + 1
}

// This is for sorting the values
let descending = times.sort({$0.1 > $1.1})
// For sorting the keys the code would be 
// let descending = times.sort({$0.0 > $1.0})
// Do whatever you want with sorted array
print(descending)

【讨论】:

    【解决方案3】:

    与空速速度相同,使用reduce 代替for-in

    extension Sequence where Self.Iterator.Element: Hashable {
        func frequencies() -> [(Self.Iterator.Element, Int)] {
            return reduce([:]) {
                var frequencies = $0
                frequencies[$1] = (frequencies[$1] ?? 0) + 1
                return frequencies
            }.sorted { $0.1 > $1.1 }
        }
    }
    

    但是请注意,这里是using reduce with a struct is not as efficient as a for-in,因为结构复制成本。因此,您通常会更喜欢for-in 的方式。

    [编辑:天哪,这篇文章与最佳答案是同一个人!]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多