我已经成功实现了一个Java程序,该程序使用了两种常见的数据结构:Tree
和Stack
以及允许用户输入树节点ID并获取有关其父级的信息的接口(interface)。您可以在这里查看该程序的最新版本at my GitHub src for this program
背景
我编写的这个临时程序用于通过比较包含以下内容的文件中的数据来研究数百种生物体之间的基因流进化:FeatureIDs = String
原语(在第一列中依次列为"ATM-0000011"
,"ATM-0000012"
等) ),由与树中特定节点上存在或不存在相关的分数组成,它们是double
原语。
数据文件如下所示:
"FeatureID","112","115","120","119","124",...//this line has all tree node IDs
"ATM-0000011",2.213e-03,1.249e-03,7.8e-04,9.32e-04,1.472e-03,... //scores on these lines
"ATM-0000012",2.213e-03,1.249e-03,7.8e-04,9.32e-04,1.472e-03,...//correspond to node ID
"ATM-0000013",0.94,1.249e-03,7.8e-04,9.32e-04,1.472e-03,...//order in the first line
... //~30000 lines later
"ATM-0036186",0.94,0.96,0.97,0.95,0.95,...
问题
以前,仅从数据文件中创建一个 double 数组的2D数组就足够了(该数组排除了文件中的第一行和FeatureID,因为它们是字符串),然后使用2D数组生成
double
堆栈。根据用户输入和Tree
的确定,将为父节点和子节点建立堆栈。然后,将同时弹出父级和子级堆栈中的数据(从而确保比较了相同的FeatureID,而不必在DS中实际包含该数据),并根据它们是否满足定义的值对其值进行比较条件(即,如果两个值均> = 0.75)。如果他们这样做了,那么计数器将增加。一旦比较完成(堆栈为空),程序将返回计数。
现在,我要做的不仅仅是列出,还列出了符合比较条件的FeatureID。因此,我不希望返回表示在节点A和节点B之间满足条件的4100个FeatureID的计数器,而是要列出所有在节点A和节点B之间进行比较的4100 FeatureID
Strings
的列表。稍后将该列表另存为文件,但这在此无关紧要。这意味着我可能不得不放弃以前非常有效的double
2D数组/double
堆栈方案。问题
知道问题出在哪里,是否有一个巧妙的解决方案,可以在不向过程中添加更多数据的情况下,对输入数据文件或代码中的某个地方(tlacMain.java)进行更改?我只需要想法。
最佳答案
我不太确定我是否能正确理解您的问题,但是您可以只将当前比较的FeatureID添加到ArrayList中,然后再将其写入文件中,而不是增加计数器。
如果您需要每个比较的列表,则可以使用HashMap<Comparison, ArrayList<String>>
之类的东西。
编辑:我阅读了您的评论,并试图在不作太多更改的情况下提出解决方案:
String[] firstLine = sc.nextLine().split(regex);
//line is the line of input being read in thru the inputFile
int line = 0;
//array of doubles will hold the data to be put in the stacks
double [][] theData = new double [28420][firstLine.length];
while(sc.hasNext())
{
String lineIn = sc.nextLine();
String[] lineInAsString = lineIn.split(regex);
for(int i = 1; i < lineInAsString.length; i++)
{
theData[line][i] = Double.parseDouble(lineInAsString[i]);
}
line++;
}
sc.close();
return theData;
在
getFile()
函数的这一部分中,您将csv读入一个双矩阵。对于矩阵中的每一列i
,我们还需要相应的featureID。要同时返回doubles矩阵和具有FeatureID的列表,您需要一个容器类。class DataContainer {
public double[][] matrix;
public int[] featureIds;
public DataContainer(double[][] matrix, int[] featureIds) {
this.matrix = matrix;
this.featureIds = featureIds;
}
}
现在,我们可以更改上面的代码以同时返回两者。
String[] firstLine = sc.nextLine().split(regex);
// array of ids
int[] featureIds = new int[firstLine.length];
for(int i = 1; i < lineInAsString.length; i++)
{
featureIds[i] = Integer.parseInt(firstLine[i]);
}
// ... same stuff as before
return new DataContainer(newMatrix, featureIds);
在您的主要功能中,您现在可以提取两个结构。所以代替
double newMatrix[][] = getFile(args);
你可以写
DataContainer data = getFile(args);
double[][] newMatrix = data.matrix;
int[] featureIds = data.featureIds;
现在,您可以使用featureIds数组将其与计算中的矩阵列进行匹配。您可以为每个匹配项创建一个
int
和addedInternal
,而不是在ArrayList<Integer>
中增加一个add(id)
。然后返回ArrayList
,因此您可以将其用于该函数之外的报告。ArrayList<Integer> addedFeatureIds = addedInternal(parentStackOne, childStackOne, featureIdStack);