我正在处理2个大文件。主文件有2个字段,分别是客户名称和第二个字段,分别是客户ID。我有第二个文件,它是第一个文件的子集,只有客户名称。 我希望找到子集文件中存在的名称的客户ID。
第一个文件有3000万行,第二个文件有500万行。
我正在尝试使用字典来做,但是要花很多时间。
您能建议我一种更好的方法吗?
这是我的代码段和文件中的几行内容。
主文件
#约翰2343245
卡里姆(Karim)126754
Rob 6543289
维杰2247861
山姆2649860
....
子集第二个文件
山姆
Rob
约翰
def extract_info(sub_file,master_file):
sub_fh = open(sub_file,'r',16777216)
sub_inst_list = []
for line in sub_fh:
if line.startswith('#'):
continue
else:
name = line.rstrip()
sub_inst_list.append(name)
sub_fh.close()
out_file = "results.rpt"
outf = open(out_file,'w')
bunchsize = 10000
bunch = []
master_fh = open(master_file,'r',16777216)
for line in master_fh:
if line.startswith('#'):
continue
else:
data = line.split()
name = data[0]
if str(data[1]) == "n/a":
continue
else:
if name in sub_inst_list:
id = str(data[1])
line = "%-80s %-15s\n" % (name, id)
bunch.append(line)
if len(bunch) == bunchsize:
outf.writelines(bunch)
bunch= []
outf.writelines(bunch)
master_fh.close()
outf.close()
答案 0 :(得分:1)
更好的方法是将主文件中的所有数据放入数据库中,然后根据第二个文件中的键查找值:
private List<Task> taskEventList = new List<Task>();
public async Task ProcessStart()
{
string messageData = "{\"name\":\"DemoData\",\"no\":\"111\"}";
RegistryManager registryManager;
Parallel.ForEach(deviceList, async (device) =>
{
// get details for each device and use key to send message
device = await registryManager.GetDeviceAsync(device.DeviceId);
SendMessages(device.DeviceId, device.Key, messageData);
});
if (taskEventList.Count > 0)
{
await Task.WhenAll(taskEventList);
}
}
private void SendMessages(string deviceId, string Key, string messageData)
{
DeviceClient deviceClient = DeviceClient.Create(hostName, new DeviceAuthenticationWithRegistrySymmetricKey(deviceId, deviceKey), Microsoft.Azure.Devices.Client.TransportType.Mqtt);
//created separate Task
var taskEvents = Task.Run(() => ProcessMessages(deviceId, string messageData));
taskEventList.Add(taskEvents);
}
private async Task ProcessMessages(string deviceId, string messageData)
{
var startTime = DateTime.UtcNow;
while (DateTime.UtcNow - startTime < TimeSpan.FromMinutes(15))
{
await deviceClient.SendEventAsync(messageData);
}
}
答案 1 :(得分:0)
另一种可能的解决方案(可能比ForceBru的慢,但嘿,编写XD很有趣)是使用线程来大大减少时间:
from queue import Queue
from threading import Thread
q = Queue()
number_of_threads = 3
def get_customer_id():
while True:
customer_name = q.get()
with open('Master.txt', 'r') as f:
for line in f.readlines():
if customer_name.strip() in line:
print(line.strip())
break
q.task_done()
with open('Slave.txt', 'r') as f:
for line in f.readlines():
q.put(line)
for i in range(number_of_threads):
new_thread = Thread(target=get_customer_id)
new_thread.setDaemon(True)
new_thread.start()
print('main thread waiting')
q.join()
print('done')
您可以增加线程数,例如说100-200,然后让它们弯曲!尽管您的最大迭代次数接近最差情况的125,000,000,000,000,但这将在计算上非常昂贵。但是,这相当夸张,因为break
语句应该减少大量的迭代。而且,如果它运行在100个线程中,那么您可以在将数字从break
中减少后将其除以100(假设您尚未达到CPU使用率最大化的情况,那么在这种情况下,多处理将更为出色)。尽管使用这种方法计算起来很简单。
这实际上与初始脚本所做的相同,但是通过划分和征服它可以将其运行很多倍!