Swift:在时间上最接近的数组中查找日期

时间:2018-10-12 07:50:42

标签: swift date

这是我第一次在Swift(macOS命令行应用程序)中进行开发。

我要遍历一个文件夹中的所有jpeg文件,将EXIF数据中没有GPS信息的文件复制出来,并为每个图像找到另外一张 GPS数据,这些图像在时间上最近( Exif时间戳)。然后我要从图像中复制GPS数据。

我有一个带有文件名(字符串),日期(Date)和GPS(字典)的结构,并为所有文件创建了一个数组(我没有在此处粘贴函数getFiles())。

struct stFile {
    var name : String
    var date : Date
    var gps : [String : AnyObject]?
}

然后我按日期字段对数组进行排序:

var files = getFiles(folder: "files://FolderToJpegs/")
var filesSorted = files.sorted(by: { $0.date.compare($1.date) == .orderedDescending })

到目前为止,我所能想到的就是一个函数,该函数可以查找日期完全相同的文件(跳过名称相同的文件,因为这与我们当前要遍历的文件相同):

for file in filesSorted {
    if (file.gps == nil) {
        if let closesdate = filesSorted.first(where: { $0.date.compare(file.date) == ComparisonResult.orderedAscending && $0.name != file.name }) {
            print("The closest date to \(file.date) is \(closesdate.date).")
        }
    }
}

由于我是新手,所以我想知道版本4中是否已经有一种简单的方法来完成此任务。我想一种方法是在第一个迭代中嵌套另一个迭代并计算时间差。

谢谢!

修改

好的,到目前为止,我想出了一种解决方案,可以计算一个元素与每个其他元素之间的时间差,这些元素具有gps数据(.gps!= nil):

for (index, _) in filesSorted.enumerated()
{
    if filesSorted[index].gps == nil
    {
        var timeDiffPrev = Double.greatestFiniteMagnitude
        var closestFile:stFile?

        for fileWithGPS in filesSorted
        {
            if(filesSorted[index].name != fileWithGPS.name && fileWithGPS.gps != nil)
            {
                let timeDiff = abs(filesSorted[index].date.timeIntervalSince(fileWithGPS.date))
                if(timeDiff < timeDiffPrev)
                {
                    closestFile = fileWithGPS
                }
                timeDiffPrev = timeDiff
            }
        }
        if(closestFile != nil)
        {
            filesSorted[index].gps = closestFile?.gps
        }
    }
}

1 个答案:

答案 0 :(得分:0)

如果“最接近”是指“最新”,那么这是我为您提供的解决方案:

首先是对我们有帮助的扩展:

extension Collection where Element: Hashable {
    var orderedSet: [Element]  {
        var set = Set<Element>()
        return compactMap { set.insert($0).inserted ? $0 : nil }
    }
}

由于此扩展程序,我们将从集合中删除重复项。 但是现在我们需要您的结构符合Hashable协议。

extension stFile: Hashable {
    static func == (lhs: stFile, rhs: stFile) -> Bool {
        return lhs.name == rhs.name
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}

由于上述原因,我们可以创建如下功能:

func getLatest() -> stFile? {
    return files.orderedSet.filter({$0.gps != nil}).sorted(by: {$0.date.compare($1.date) == .orderedDescending}).first
}

其中:

  • orderedSet删除重复项(具有相同名称的文件)
  • filter删除没有GPS数据的文件
  • sorted正在对先前操作的剩余内容进行排序(并且因为使用了orderedSetfilter 之前,它排序的文件可能较少)

编辑:

起初,我误解了这个问题。我希望这就是您的意思:

func copyGPS() -> [stFile] {
    let uniqueFiles = files.orderedSet.sorted(by: {$0.date.compare($1.date) == .orderedDescending})
    var filesWithGPS : [stFile] = []
    for file in uniqueFiles {
        if file.gps == nil {
            let gps = uniqueFiles.filter({$0.gps != nil && $0.date > file.date}).first?.gps
            filesWithGPS.append(stFile(name: file.name, date: file.date, gps: gps))
        } else {
            filesWithGPS.append(file)
        }
    }
    return filesWithGPS
}