我想找到一个使用C ++的编程解决方案。
我有一个每个27MB大小的900个文件。 (只是为了告知这个问题)。
每个文件都有55K行和不同的列。但标题表示列
我想按照w.r.t的顺序将行排序为列值。
我为此编写了排序算法(绝对是我的新手尝试,你可能会说)。 该算法适用于少数数字,但对于较大的数字则失败。
以下是相同的代码: 我定义在主代码中使用的基本函数:
int getNumberOfColumns(const string& aline)
{
int ncols=0;
istringstream ss(aline);
string s1;
while(ss>>s1) ncols++;
return ncols;
}
vector<string> getWordsFromSentence(const string& aline)
{
vector<string>words;
istringstream ss(aline);
string tstr;
while(ss>>tstr) words.push_back(tstr);
return words;
}
bool findColumnName(vector<string> vs, const string& colName)
{
vector<string>::iterator it = find(vs.begin(), vs.end(), colName);
if ( it != vs.end())
return true;
else return false;
}
int getIndexForColumnName(vector<string> vs, const string& colName)
{
if ( !findColumnName(vs,colName) ) return -1;
else {
vector<string>::iterator it = find(vs.begin(), vs.end(), colName);
return it - vs.begin();
}
}
////////// I like the Recurssive functions - I tried to create a recursive function
///here. This worked for small values , say 20 rows. But for 55K - core dumps
void sort2D(vector<string>vn, vector<string> &srt, int columnIndex)
{
vector<double> pVals;
for ( int i = 0; i < vn.size(); i++) {
vector<string>meancols = getWordsFromSentence(vn[i]);
pVals.push_back(stringToDouble(meancols[columnIndex]));
}
srt.push_back(vn[max_element(pVals.begin(), pVals.end())-pVals.begin()]);
if (vn.size() > 1 ) {
vn.erase(vn.begin()+(max_element(pVals.begin(), pVals.end())-pVals.begin()) );
vector<string> vn2 = vn;
//cout<<srt[srt.size() -1 ]<<endl;
sort2D(vn2 , srt, columnIndex);
}
}
现在主要代码:
for ( int i = 0; i < TissueNames.size() -1; i++)
{
for ( int j = i+1; j < TissueNames.size(); j++)
{
//string fname = path+"/gse7307_Female_rma"+TissueNames[i]+"_"+TissueNames[j]+".txt";
//string fname2 = sortpath2+"/gse7307_Female_rma"+TissueNames[i]+"_"+TissueNames[j]+"Sorted.txt";
string fname = path+"/gse7307_Male_rma"+TissueNames[i]+"_"+TissueNames[j]+".txt";
string fname2 = sortpath2+"/gse7307_Male_rma"+TissueNames[i]+"_"+TissueNames[j]+"4Columns.txt";
vector<string>AllLinesInFile;
BioInputStream fin(fname);
string aline;
getline(fin,aline);
replace (aline.begin(), aline.end(), '"',' ');
string headerline = aline;
vector<string> header = getWordsFromSentence(aline);
int pindex = getIndexForColumnName(header,"p-raw");
int xcindex = getIndexForColumnName(header,"xC");
int xeindex = getIndexForColumnName(header,"xE");
int prbindex = getIndexForColumnName(header,"X");
string newheaderline = "X\txC\txE\tp-raw";
BioOutputStream fsrt(fname2);
fsrt<<newheaderline<<endl;
int newpindex=3;
while ( getline(fin, aline) ){
replace (aline.begin(), aline.end(), '"',' ');
istringstream ss2(aline);
string tstr;
ss2>>tstr;
tstr = ss2.str().substr(tstr.length()+1);
vector<string> words = getWordsFromSentence(tstr);
string values = words[prbindex]+"\t"+words[xcindex]+"\t"+words[xeindex]+"\t"+words[pindex];
AllLinesInFile.push_back(values);
}
vector<string>SortedLines;
sort2D(AllLinesInFile, SortedLines,newpindex);
for ( int si = 0; si < SortedLines.size(); si++)
fsrt<<SortedLines[si]<<endl;
cout<<"["<<i<<","<<j<<"] = "<<SortedLines.size()<<endl;
}
}
有人可以建议我这样做的更好方法吗? 为什么没有更大的价值观。 ?
此查询感兴趣的主要功能是Sort2D功能。
感谢您的时间和耐心。
普拉萨德。
答案 0 :(得分:2)
我不确定为什么你的代码会崩溃,但在这种情况下递归只会降低代码的可读性。我怀疑这是一个堆栈溢出,因为你没有在每次调用中使用太多的堆栈空间。
C ++已经有std::sort
,为什么不使用它呢?你可以这样做:
// functor to compare 2 strings
class CompareStringByValue : public std::binary_function<string, string, bool>
{
public:
CompareStringByValue(int columnIndex) : idx_(columnIndex) {}
bool operator()(const string& s1, const string& s2) const
{
double val1 = stringToDouble(getWordsFromSentence(s1)[idx_]);
double val2 = stringToDouble(getWordsFromSentence(s2)[idx_]);
return val1 < val2;
}
private:
int idx_;
};
然后对你要调用的行进行排序
std::sort(vn.begin(), vn.end(), CompareByStringValue(columnIndex));
现在,有一个问题。这会很慢,因为在同一个字符串上多次调用stringToDouble
和getWordsFromSentence
。您可能希望生成一个单独的向量,该向量已预先计算每个字符串的值,然后让CompareByStringValue
仅将该向量用作查找表。
另一种方法是将字符串插入std::multimap<double, std::string>
。只需将条目插入(value, str)
,然后逐行读取。这更简单但更慢(尽管具有相同的大O复杂度)。
编辑:清除了一些不正确的代码并从binary_function
派生。
答案 1 :(得分:1)
您可以尝试一种不涉及递归的方法。如果您的程序使用具有较大值的Sort2D函数崩溃,那么您可能会溢出堆栈(使用大量函数调用的递归的危险)。尝试另一种排序方法,可能使用循环。
答案 2 :(得分:0)
问题是您的代码少于您为工作选择的工具。这纯粹是一个文本处理问题,所以选择一个好的工具。在Unix的情况下,最好的工具是Bash和GNU coreutils。在Windows上,您可以使用PowerShell,Python或Ruby。 Python和Ruby也适用于任何Unix风格的机器,但大多数Unix机器都安装了Bash和coreutils。
让$FILES
保存要处理的文件列表,由空格分隔。这是Bash的代码:
for FILE in $FILES; do
echo "Processing file $FILE ..."
tail --lines=+1 $FILE |sort >$FILE.tmp
mv $FILE.tmp $FILE
done
答案 3 :(得分:0)
sort2D
崩溃,因为你继续分配一个字符串数组进行排序,然后按值传递它,实际上是使用O(2 * N ^ 2)内存。如果您真的想要保留递归功能,只需通过引用传递vn
,而不必担心vn2
。如果您不想修改原始vn
,请将sort2D
的正文移至另一个函数(例如sort2Drecursive
)并从sort2D
调用该函数。
你可能想要另外看一下sort2D
,因为你正在为O(N + N * log(N))做一些O(N ^ 2)工作。