【问题标题】:Referencing 2 coordinates and check differential value参考 2 个坐标并检查差分值
【发布时间】:2019-11-13 16:33:41
【问题描述】:

这个问题是我之前提出的问题的延伸。

Setting a reference number and comparing that to other data in textfile

我在一个文本文件中有一组 X 和 Y 数据坐标。

Recorded Data 1

X: 1081.02409791506 Y:136.538121516361
Data collected at 208786.9115


Recorded Data 2

X: 1082.82841293328 Y:139.344405668078
Data collected at 208810.0446

Recorded Data 4

X: 1525.397051187 Y:1163.1786031393
Data collected at 245756.8823

Recorded Data 5

X: 1524.98201445054 Y:1166.38589429581
Data collected at 245769.489

Recorded Data 6

X: 509.002294087998 Y:913.213486303154
Data collected at 277906.6251

Recorded Data 7

X: 479.826998339658 Y:902.689393940613
Data collected at 277912.9958

我想将第一组数据 X: 1081.02409791506 Y:136.538121516361 设置为参考点,然后分别用下一组数据 X 和 Y 减去自身,并检查结果值是否在 100 内的 X 和 Y 差异值,如果是,则继续操作。参考点应继续对以下数字执行此操作,直到到达± 100 range 之外。一旦在100 range之外,现在这组数据是X: 1525.397051187 Y:1163.1786031393,因为第一个数据和这个数据的差值超过了100,那么现在这组数据是下一个参考点,做同样的事情并减去下面的数据并检查结果值是否在100 内。一旦在100 range 之外,下一个数字是X: 509.002294087998 Y:913.213486303154,现在,那是新的参考点,并且做同样的事情。那是我的目标。简而言之,应该将参考点移动到一个新文件中。

此代码能够执行上述操作,但仅适用于下面显示的数字。

278
299
315
360
389
400
568
579
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ReadTextFile
{
    class Program
    {
        static void Main(string[] args) 
        {       string inputFile = @"C:\Users\Student\Desktop\ConsoleApp1\ConsoleApp1\Data\TextFile.txt"; // INPUT FILE
                string outputFile = @"C:\Users\Student\Desktop\Test.txt";  // OUTPUT FILE

                string[] data = File.ReadAllLines(inputFile);  // READING FORM FILE
                int TotalLine = data.Length;  // COUNT TOTAL NUMBER OF ROWS
                List<string> FinalList = new List<string>();  // INITIALIZE LIST FOR FINAL RESULT

            double CurrentNumber = double.Parse(data[0]), NextNumber, diff;  // INITIALIZE OF LOCAL VARIABLES, CURRENT NUMBER = FIRST NUMBER FROM FILE

            for (int cntr = 1; cntr < TotalLine; cntr++) // FOR LOOP FOR EACH LINE
            {
                    NextNumber = double.Parse(data[cntr]);  //PARSING NEXT NUMBER
                    diff = CurrentNumber - NextNumber;  // GETTING DIFFERENCE

                   if (diff <= 100 && diff >= -100)  // MATCH THE DIFFERENCE
                   {
                        continue;  // SKIP THE LOGIC IF DIFFERENCE IS LESS THEN 100
                   }
                   else
                   {
                        FinalList.Add(CurrentNumber.ToString());  // ADDING THE NUMBER TO LIST
                        CurrentNumber = NextNumber;  // POINTING TO NEXT NUMBER
                   }

            }
                FinalList.Add(CurrentNumber.ToString());  // ADDING LAST NUMBER
                foreach (string d in FinalList)  // FOR EACH LOOP TO PRINT THE FINAL LIST
                Console.WriteLine(d);
                File.WriteAllLines(outputFile, FinalList);  // SAVING TO THE FILE


        }

我如何为 2 个坐标做同样的事情?

第一个条件:X 或 Y 至少有 1 个微分值在± 100 range 之外,该组数据是新的参考数据。

第二个条件:如果x和Y的差值都在± 100 range之内,我们必须继续操作。

【问题讨论】:

  • 每种坐标类型都有一个文件,一个用于 X,一个用于 Y?
  • 不,我显示的是 1 个文本文件
  • 该文件的外观如何?就像上面发布的代码一样?带有标题“记录数据”和空白行等...?
  • 我已经编辑好了,请再看一遍问题

标签: c# interaction


【解决方案1】:

这里有一个解决方案,前提是源文件内容如上:

记录数据 1

X:1081.02409791506 Y:136.538121516361
在 208786.9115 收集的数据

记录数据 2

X:1082.82841293328 Y:139.344405668078
数据采集​​于 208810.0446

..

和目标文件如下:

X:1081.02409791506 Y:136.538121516361
X:1525.397051187 Y:1163.1786031393
..

解决方案

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var points = ParseFromFile(
                @"C:\Users\Student\Desktop\ConsoleApp1\ConsoleApp1\Data\TextFile.txt");

            RenderToFile(
                @"C:\Users\Student\Desktop\Test.txt",
                Merge(points).ToArray());
        }

        static void RenderToFile(string fileName, (double x, double y)[] points)
        {
            var formatProvider = new CultureInfo("en-US", false);
            var builder = new StringBuilder();
            foreach (var point in points)
            {
                builder.Append(
                    $"X: {point.x.ToString(formatProvider)} Y:{point.y.ToString(formatProvider)}");
            }
            System.IO.File.WriteAllText(fileName, builder.ToString());
        }

        static (double x, double y)[] ParseFromFile(string fileName)
        {
            return Parse(System.IO.File.ReadAllText(fileName)).ToArray();
        }

        static IEnumerable<(double x, double y)> Merge((double x, double y)[] points)
        {
            points = points ?? throw new ArgumentNullException(nameof(points));
            if (points.Length == 0) yield break;
            var std = 100;
            var current = points[0];
            if (points.Length == 1)
            {
                yield return current;
                yield break;
            }
            for (var i = 1; i < points.Length; i++)
            {
                var dx = Math.Abs(points[i].x - current.x);
                var dy = Math.Abs(points[i].y - current.y);

                if (dx <= std && dy <= std)
                {
                    continue;
                }

                yield return current;
                current = points[i];
            }
            yield return current;
        }

        static IEnumerable<(double x, double y)> Parse(string raw)
        {
            var formatProvider = new CultureInfo("en-US", false);
            var pattern = new Regex(@"^[Xx][:] (?<x>\d*([.]\d+)?) [Yy][:](?<y>\d*([.]\d+)?)$");
            raw = raw ?? throw new ArgumentNullException(nameof(raw));
            foreach (var line in raw.Split(
                Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Where(
                line => line.ToLowerInvariant().StartsWith("x")))
            {
                var match = pattern.Match(line);
                var xToken = match.Groups["x"].Value.Trim();
                var yToken = match.Groups["y"].Value.Trim();
                var x = double.Parse(xToken, formatProvider);
                var y = double.Parse(yToken, formatProvider);
                yield return (x: x, y: y);
            }
        }
    }
}

解释

首先我们需要解析数据。

格式提供程序需要从带有十进制分隔符. 的固定字符串中正确解析double

// can parse 1525.397051187, but not 1525,397051187
// en-US is the format you comply with
// 'false' is required to use the default culture settings, not any user overrided
var formatProvider = new CultureInfo("en-US", false);

该模式确保我们正确解析xy 坐标。

// X: 1525.397051187 Y:1163.1786031393
// we use named groups to capture x (?<x>\d*([.]\d+)?)
//                            and y (?<y>\d*([.]\d+)?)
var pattern = new Regex(@"^[Xx][:] (?<x>\d*([.]\d+)?) [Yy][:](?<y>\d*([.]\d+)?)$");

解析后,我们可以根据您的规范合并 (x,y) 坐标。 std 是我们的增量允许的标准偏差(dxdy)。

var dx = Math.Abs(points[i].x - current.x);
var dy = Math.Abs(points[i].y - current.y);

if (dx <= std && dy <= std)
{
    continue;
}

关于IEnumerable&lt;T&gt;的注释:

使用它作为返回值允许我们使用yield 语法。这称为生成器函数。

关于值元组(double x, double y)的说明:

我们可以使用命名元组来避免创建“愚蠢”的中间类。

【讨论】:

  • 考虑为您的方法添加解释
  • 当然,我不知道这个网站会出现这种情况。
  • 感谢您的努力,但是如果我们可以从文本文件中读取会更好,因为文本文件中会有更多的数据集(例如 50+)而不是列出数据集代码本身中的数据。例如,在我的代码中,我从文本文件中读取数据,而不是列出
  • 从文本文件中读取只是将File.ReadAllText() 传递给我的Parse 方法。你要我添加代码来读写文本文件吗?
  • 我添加了一张图片,我认为有些指针没有声明
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多