大量数据查重

     本来到软工所是为了做作业和看书的,结果,很不务正业的被一个问题吸引了,这个任务是:从文件中读入一系列格式化好的数据,如

 

  int           int              int        int     float     float

90900 1442373573 1486014884 0 0.0125 0.0949473

90900 1442373573 1485883012 0 0.0125 0.0945844

90900 836615420 1488523911 2 0.0125 0.00650644

90900 1277583173 1488377356 3 0.0125 0.089611

90900 598391375 1488217313 2 0.0125 0.00790251

90900 1277583173 1306110622 3 0.0125 0.10079

90900 1277583173 1294971886 3 0.0125 0.0947241     


     然后以某个数据为Key进行查重(一看发现第一排都一样),思路其实相当简单,在输入数据的时候构建Hash表或者树形查找结构(直接使用STL的Set或者Map即可)数据量很大,大约150M以上的数据。 所以其实最大的问题在于怎么做文件操作才可以尽可能快的完成,考虑到150M内存放的下,而传统的一次读取一个数据或者一次一行的操作都要频繁的IO操作,性能必然达不到要求,所以需要一次性将整个文件读入内存,然后再对内存中的格式化数据进行处理。

     格式化读入数据我用的是sscanf不知道C++有没其他好的方法,至少我感觉同时使用C++的IO库和C的库是件非常蛋疼的事情,经常会发生各种莫名其妙的错误,还是少用为好。但C++标准的IO库的效率实在是。。。如果不优化绝对满足不了要求的。以前搞ACM的时候的教条,如果你不想TimeOut,那就不要用cin,cout。学学Scanf和Printf吧,少年。记忆尤深啊。


     如果内存限制的情况就是尽可能的分割块来求解了,如果仅仅是查重的话,说明重复的数量必然不大,查重的数据结构可以常驻内存。只需要把IO读写的操作考虑清楚就OK了。


    在string 的substr上面纠结了很久,因为我的印象中是传入两个参数,一个是开始索引,另一个是结束的。。所以该函数的行为让我很不解,后面一调试发觉不对劲,结果查了下,才发现居然第二个参数是截取的字符数。。。记性不好啊。。确实应该多写才行,string 处理在大三暑假做课程设计时候经常用的,两年多了就忘的差不多了。


不多扯了,代码如下:

 

 

#include<vector>
#include <string>
#include <fstream>
#include<iostream>
#include <set>
using namespace std;
//the google data structure
struct Data
{
	int Time;
	int JobID;
	int TaskID;
	int JobType;
	float NrmlTaskCore;
	float NrmlTaskMem;
};
//Store the data into a vector
typedef vector<Data> google_data;

void initData(const string& s_data, google_data& t_data)
{
	//cout<<"init"<<endl;
	string line;
	long index = 0;             //记录目前s_data读取的位置
	long lineStart;
	long fileSize = s_data.size();
	Data tmp;
	set<int> jobSet;
	set<int> taskSet;
	index = s_data.find_first_of(char(10), index);
	++index;
	while(index<=fileSize)    //防止溢出
	{
		lineStart = index;
		index = s_data.find_first_of(char(10), index);
		if(index==-1)            //真正结束循环的地方
			break;
		//解析string,存为六个字段
		line = s_data.substr(lineStart, index-lineStart);
		sscanf(line.c_str(), "%d %d %d %d %f %f", &tmp.Time,&tmp.JobID, &tmp.TaskID, &tmp.JobType, &tmp.NrmlTaskCore,&tmp.NrmlTaskMem);
		t_data.push_back(tmp);
		index +=1;
	}
	cout<<"The total lines:"<<t_data.size()<<endl;
	//遍历解析后的数据,去除重复的jobID和taskID
	google_data::iterator itr = t_data.begin();
	while(itr != t_data.end())
	{
		jobSet.insert((*itr).JobID);
		taskSet.insert((*itr).TaskID);
		itr++;
	}
	cout<<"The unique jobs :"<<jobSet.size()<<endl;
	cout<<"The unique tasks:"<<taskSet.size()<<endl;
}

char * readFile(const char* filename)
{
	//cout<<"begin reading..."<<endl;
	filebuf *pbuf;
	ifstream filestr;
	long size;
	char *buffer;
	//要读入整个文件,必须采用二进制打开
	filestr.open(filename, ios::binary);
	//获取filestr对应buffer对象的指针
	pbuf = filestr.rdbuf();
	//调用buffer对象方法获取文件大小
	size = pbuf->pubseekoff(0, ios::end, ios::in);
	pbuf->pubseekpos(0, ios::in);
	//分配内存空间
	buffer = new char[size];
	//获取文件内容
	pbuf->sgetn(buffer, size);
	filestr.close();
	return buffer;
}

int main()
{
	google_data t_data;
	//cout<<"read file"<<endl;
	char* buf = readFile(".//google-cluster-data-1.csv");
	//将读入文件以字符串形式存入fileData中
	string fileData(buf);
	cout<<"start computing, please wait about more than 1 minutes..."<<endl;
	//核心, 处理数据(解析,计算出某个字段的不重复总数)
	initData(fileData, t_data);
	//cout<<"end of sparse.."<<endl;
//	system("pause");
	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值