我有2个文本文件default.txt和current.txt。
default.txt:
ab_abcdefghi_EnInP005M3TSub.csv FMR: 0.0009 FNMR: 0.023809524 SCORE: -4 Conformity: True
ab_abcdefghi_EnInP025M3TSub.csv FMR: 0.0039 FNMR: 0 SCORE: -14 Conformity: True
ab_abcdefghi_EnInP050M3TSub.csv FMR: 0.01989 FNMR: 0 SCORE: -18 Conformity: True
ab_abcdefghi_EnInP075M3TSub.csv FMR: 0.0029 FNMR: 0 SCORE: -17 Conformity: True
ab_abcdefghi_EnInP090M3TSub.csv FMR: 0.0002 FNMR: 0 SCORE: -7 Conformity: True
current.txt看起来像这样
ab_abcdefghi_EnUsP005M3TSub.csv FMR: 0.0041 FNMR: 0 SCORE: -14 Conformity: True
ab_abcdefghi_EnUsP025M3TSub.csv FMR: 0.00710000000000001 FNMR: 0 SCORE: -14 Conformity: True
ab_abcdefghi_EnUsP050M3TSub.csv FMR: 0.0287999999999999 FNMR: 0 SCORE: -21 Conformity: True
ab_abcdefghi_EnUsP090M3TSub.csv FMR: 0.0113 FNMR: 0 SCORE: -23 Conformity: True
我需要做的是从默认值(默认当前值)中减去当前值。
E.g:
FMR_DIFF = FMR(default) - FMR(test)
FNMR_DIFF = FNMR(default) - FNMR(test)
SCORE_DIFF = SCORE(default) - SCORE(test)
我需要在一个文本文件中输出它,输出看起来像这样
O / P:
result: 005M3TSub FMR_DIFF: -0.0032 FNMR_DIFF: 0.023809524 SCORE_DIFF: 10
我想在C#中这样做。到目前为止,我已尝试在两个文件中读取行。我能够比较它们。我无法理解我需要实现的逻辑。我是编程新手。任何帮助表示赞赏。
答案 0 :(得分:1)
为了比较这些值,您首先必须解析它们。您可以创建一个表示单行(False / Non-False)MatchRates的类:
public class MatchRateLine
{
public int LineNumber { get; set; }
public decimal FMR { get; set; }
public decimal FNMR { get; set; }
public int Score { get; set; }
public bool Conformity { get; set; }
}
然后在您的解析器中,您可以使用以下方法:
public List<MatchRateLine> ParseFile(string filename)
{
var result = new List<MatchRateLine>();
using (var reader = new StreamReader(filename))
{
string line;
while ((line = reader.ReadLine()) != null)
{
result.Add(ParseLine(line));
}
}
return result;
}
进行实际解析的一种方法是:
public MatchRateLine ParseLine(string line)
{
var result = new MatchRateLine();
int fmrPosition = line.IndexOf("FMR: ");
int fmnrPosition = line.IndexOf("FMNR: ");
string fmrValueString = line.Substring(fmrPosition, fmnrPosition - fmrPosition);
decimal fmrValue;
if (decimal.TryParse(fmrValueString, out fmrValue))
{
result.FMR = fmrValue;
}
// repeat for other values
return result;
}
在解析器中,我已经定义“A line的FMR值” “'FMR:'和'FMNR:'之间的文本,解析为十进制”。您必须为要提取的每个值应用此逻辑。
现在当你有两个集合时,你可以循环它们并比较它们的值和诸如此类的东西:
var defaultLines = Parser.ParseFile("default.txt");
var currentLines = Parser.ParseFile("current.txt");
您的实际问题似乎是您可能希望比较default
和current
中的特定行,但您无法识别彼此属于的行。正如第5行ab_abcdefghi_EnInP090M3TSub
中的default
和ab_abcdefghi_EnUsP090M3TSub
中的current
所见,第4行(注意In/Us
)。
为此,您可以使用属性扩展MatchRateLine
类,其中存储文件名或其子串的含义,以便您可以通过此值在两个列表中找到唯一的行。
您可以在Substring()
方法中再次使用ParseLine()
方法:
// Position: 0123456789012345678901234567890
// Filename: "ab_abcdefghi_EnInP090M3TSub.csv"
result.ReportCode = line.Substring(17, 6);
这会导致生成的MatchRateLine
具有ReportCode
属性,其值为P090M3
。
再次给出两个行列表:
var p090m3DefaultLine = defaultLines.First(l => l.ReportCode == "P090M3");
var p090m3CurrentLine = currentLines.First(l => l.ReportCode == "P090M3");
var fmrDiff = p090m3DefaultLine.FMR - p090m3CurrentLine.FMR;
请注意,此代码对格式做了很多假设,并且在被解析的行与该格式不匹配时会抛出异常。
答案 1 :(得分:1)
这是一个有趣的问题。请检查解决方案。它未正确优化。
首先,我们创建一个简单的FileStructure类来表示String:
public class DefaultFileStructure
{
public string FileId;
public decimal FMR;
public decimal FNMR;
public int Score;
public bool Conformity;
}
定义解析的常量键名。
private static string DEFAULT_KN = "tv_rocscores_DeDeP";
private static string TEST_KN = "tv_rocscores_FrFrP";
现在,解析文件并将数据存储在列表结构中。
private List<DefaultFileStructure> GetFileStructure(string filePath, string keyName)
{
List<DefaultFileStructure> _defaultFileStructure = new List<DefaultFileStructure>();
if(!File.Exists(filePath))
{
Console.WriteLine("Error in loading the file");
}else{
string[] readText = File.ReadAllLines(filePath);
foreach (string s in readText)
{
_defaultFileStructure.Add(ParseLine(s, keyName));
}
}
return _defaultFileStructure;
}
private DefaultFileStructure ParseLine(string Line, string Keyname)
{
DefaultFileStructure _dFileStruc = new DefaultFileStructure();
string[] groups = Line.Split(new[] { ' ', ' ' },StringSplitOptions.RemoveEmptyEntries);
/* -- Format Strucure, if the log provide same format always..
Can also implement Expando concepts of C# 5.0 ***
0[tv_rocscores_DeDeP005M3TSub.csv]
1[FMR:]
2[0.0009]
3[FNMR:]
4[0.023809524]
5[SCORE:]
6[-4]
7[Conformity:]
8[True]
*/
_dFileStruc.FileId = groups[0].Replace(Keyname, "");
_dFileStruc.FMR = decimal.Parse(groups[2]);
_dFileStruc.FNMR = decimal.Parse(groups[4]);
_dFileStruc.Score = int.Parse(groups[6]);
_dFileStruc.Conformity = bool.Parse(groups[8]);
return _dFileStruc;
}
根据您的问题匹配差异并获得定义的结果。
public void getDiff(String FirstFile, string SecondFile, string ResultFile)
{
try
{
//check if file exits....
if (!File.Exists(FirstFile)) { return; }
if (!File.Exists(SecondFile)) { return; }
//Keep the result String..
StringBuilder ResultBuilder = new StringBuilder();
//Get the List of default file.
List<DefaultFileStructure> DefaultList = GetFileStructure(FirstFile, DEFAULT_KN);
//Get the List of test file.
List<DefaultFileStructure> TestList = GetFileStructure(SecondFile, TEST_KN);
//Get the diff and save in StringBuilder.
foreach (DefaultFileStructure defFile in DefaultList)
{
bool checkALL = false;
foreach (DefaultFileStructure testFile in TestList)
{
//Compare the file for diff.
if (defFile.FileId == testFile.FileId)
{
checkALL = false;
ResultBuilder.AppendLine(String.Format("result: {0} FMR_DIFF: {1} FNMR_DIFF: {2} SCORE_DIFF: {3}", defFile.FileId, defFile.FMR - testFile.FMR, defFile.FNMR - testFile.FNMR, defFile.Score - testFile.Score));
break;
}
else
{
checkALL = true;
}
}
if (checkALL == true)
{
ResultBuilder.AppendLine(String.Format("result: {0} FMR_DIFF: {1} FNMR_DIFF: {2} SCORE_DIFF: {3}", defFile.FileId, "N/A", "N/A", "N/A"));
}
}
//File processing completed.
using (StreamWriter outfile = new StreamWriter(ResultFile))
{
outfile.Write(ResultBuilder.ToString());
}
}
catch (Exception ex)
{
throw ex;
}
}
请调用以下方法。
getDiff(@"I:\Default_DeDe_operational_points_verbose.txt",
@"I:\FrFr_operational_points_verbose.txt",
@"I:\Result.txt");
谢谢, 阿吉特
答案 2 :(得分:0)
您必须指定输出中必须包含哪些行:默认情况下每个“文件”.csv?从现在开始?两者(如果在两个文件中的一个中缺少一个,输出必须仍然包含此csv)?
一旦你知道,你可以实现你的逻辑:
为流程创建方法。它将:
检查当前文件的结构:如果无效,请停止进程
然后处理比较(见后)
public void comparisonGenerator() {
// HERE: add currentFile check
// Initialization
List<FileLine> defaultLines = new List<FileLine>();
List<FileLine> currentLines = new List<FileLine>();
// HERE: add file reading to populate defaultLines and currentLines
// Comparison
foreach(FileLine item in defaultLines)
{
// for the item with the same name (using Linq, you could do it easily):
FileLine cLine = currentLines.Single(l => l.CsvName.Equals(item.CsvName));
if(cLine != null)
{
processedLine = String.Format("result: {0} FMR_DIFF: {1} FNMR_DIFF: {2} SCORE_DIFF: {3}", item.CsvName, item.FmrValue - cLine.FmrValue, item.FnmrValue - cLine.FnmrValue, item.ScoreValue - cLine.ScoreValue);
// HERE: add this line to future output
}
}
// When all lines are processed, write the output to a file using FileStream
}