Мне трудно обдумать это.
У меня есть два CSV, которые составляют оптоволоконную сеть: один для широты, один для долготы. Они были взяты из файла KMZ, и оба CSV-файла состоят из 170 тыс. строк каждый из-за плохо построенного KMZ.
У меня есть CSV потенциальных клиентов, которых я хочу сравнить с оптоволоконной сетью. Если минимальное расстояние (рассчитанное по формуле Хаверсина) меньше 5280 футов, оно будет напечатано в выходной CSV-файл.
Я успешно справлялся с этим в прошлом, когда не было так много пар широта/долгота: 20 тысяч в прошлом, но теперь у нас есть 170 тысяч. Выходной CSV-файл становится огромным, как вы можете себе представить: 3 миллиона строк и больше.
Тогда мне нужно будет сделать проверку (обычно с использованием функции MySQL MIN(), но я уверен, что есть лучший способ), чтобы вернуть минимальное расстояние по адресу и группировать по адресу: поскольку вас действительно интересует только минимальное расстояние, по адресу. Вам не нужно несколько строк для каждого адреса.
require 'csv'
require 'haversine'
#this could be put into one file, works as is
fib_lat = CSV.read("swfl_fiber_lat.csv")
fib_long = CSV.read("swfl_fiber_long.csv")
#use zip to read both arrays at the same time
fib_coords = fib_lat.map(&:last).zip(fib_long.map(&:last))
#multiple column CSV with customer data, headers turned on
customers = CSV.read("swfl_1a_geocoded.csv", headers:true)
CSV.open('swfl-output-data-within-1mile.csv','w', :write_headers=> true, :headers => ['First Name','Last Name','Latitude','Longitude','Feet to Fiber','Address','City','State','Zip','County','Company','Title Code Description','PrimarySIC6 Description','Business Status Code Description','Phone Number','Tollfree Phonenumber','EmployeeSize Location Description','Sales Volume Location Decode','Telecommunications Expense','Email Address']) do |csv_object|
fib_coords.each do |fib_lat, fib_long|
customers.each do |cust|
if (Haversine.distance(cust[2].to_f, cust[3].to_f, fib_lat.to_f, fib_long.to_f).to_feet < 5280)
data_out = ["#{cust[0]},#{cust[1]},#{cust[2].to_f},#{cust[3].to_f}, #{Haversine.distance(cust[2].to_f, cust[3].to_f, fib_lat.to_f, fib_long.to_f).to_feet.round(2)},#{cust[5]},#{cust[6]},#{cust[7]},#{cust[8]},#{cust[9]},#{cust[10]},#{cust[11]},#{cust[12]},#{cust[13]},#{cust[14]},#{cust[15]},#{cust[16]},#{cust[17]},#{cust[18]}"]
csv_object << data_out
end
end
end
end
Я пытаюсь придумать способ вернуть клиента (возможно, используя .uniq
arr#min
и только минимальный адрес для каждого клиента, не запихивая это в выходной CSV. Затем, если действительно есть расстояние ниже 5280 и связанный с ним клиент, поместите только это в выходной массив CSV.
Что касается псевдокода: если расстояние является минимальным для каждого клиента, убедитесь, что значение клиента уникально, а затем вставьте его в выходной CSV. Просто не знаю на 100%, как реализовать это в моем потоке циклов.
Любое понимание приветствуется.