解决服务器崩溃问题,Ruby算法是你的救星

发表时间: 2020-06-01 16:00

全文共1399字,预计学习时长6分钟


图源:unsplash


软件工程师常常要和大量数据打交道。有时数据结构很合理,让人省心,但有时则不然,需要你去清理和整理数据,使其最大化的服务于我们的项目。


这可谓职业生涯的最大挑战了,如何不让服务器崩溃,是个值得讨论的问题。别急,Ruby算法会给你答案。


案例定义


先描述一下这个问题。首先,有一个庞大的GeoData数据集。它是一个有两个键的散列:要素和几何。几何键中的数据负责使用D3库来绘制世界地图。


但在今天的例子中,不会做任何与几何键相关的事情。我们将使用要素键来表示世界地图上每个国家的数据。


图源:unsplash


我们拥有的第二个数据集是散列数组形式的数据。需要对GeoData进行迭代,并将第二个数据集中的数据插入到GeoData中。


在开始处理数据之前,需要先获取数据。在本例中,数据具有JSON文件形式。这就是我们提取数据的方式:


require ‘json’json_file = File.open“CombinedGeoData.json”data = JSON.load json_file


暴力的解决方案


data['features'].each{|n|      second_dataset.each{|j|           if j[:country] == n['properties']['name']               n['properties']['some_property']= j[:some_property]           end    }}


首先,我们将尝试一个简单直观的解决方案。先对要素数组进行迭代,然后在每个循环中,将对第二个数据集进行迭代。最后使用if语句来查找匹配国家/地区并插入数据。


解决方案非常完美,但是该解决方案的复杂之处在于O(n*m),而不是n²,因为使用的是不同的数组,但是逻辑相同。随着数组大小的增长,该解决方案的复杂性也将呈指数级增长。


更简洁的解决方案


现在,让我们尝试创建更理想的解决方案!我们的目标是仅使用一个循环即可完成所有的数据操作。


index = 0data['features'].each{|n|       if second_dataset[index][:country] ==n['properties']['name']         n['properties']['some_property']= second_dataset[index]             [:some_property]         index += 1       end}


我们需要循环外的索引值,将使用此值来访问第二个数据集中的元素。另外,还需要一个if语句来找到所需的国家。只有找到了国家才会增加索引。


使用此解决方案,O(n)复杂性的问题就完美解决了。


图源:unsplash


但是这里有点问题。第二个数据集中的数据已按字母顺序排列,但是第一个数据集中的数据不是按此顺序排列的,所以我们的算法将不起作用,因为数据集的排列顺序不一致。


让我们来解决这个问题!


sorted_data =data[‘features’].sort_by{|n| [n[‘properties’][‘name’]}


这两行代码将按国家/地区名称对所有内容进行排序,然后重写数据集。但是还是有错误:


`sort_by’: comparison of Stringwith nil failed


这意味着数组中有nil值,必须调整排序算法。当Ruby比较数组时,它会先比较第一个元素,并且仅在第一个元素相等的情况下才会比较第二个元素。?1:0会保证Fixnum作为第1个元素,因此应该不会出现错误。


sorted_data =data[‘features’].sort_by{|n| [n[‘properties’][‘name’] ? 0 : 1, n[‘properties’][‘name’]]}data[‘features’] = sorted_data


这样就可以得到一个有序的数组,并且这个简洁的循环也可以正常工作。


人们通常更愿意使用做起来简单的解决方案,但殊不知这种“笨办法”很可能成本更高。随着项目规模的增长,我们会面临更大更多的数据集,必须去考虑代码所消耗的复杂性资源,这样我们才能保持服务器的正常运转。


留言点赞关注

我们一起分享AI学习与发展的干货

如转载,请后台留言,遵守转载规范