Java流表达式将字符串解析为double[m][n](其中n大小可变)

huangapple go评论79阅读模式
英文:

Java streams expression parse string to a double[m][n] (with n varying size)

问题

代码部分不要翻译,只返回翻译好的内容:

作为解析配置字符串的一部分,我想将一个字符串转换为双重[][]数组。配置字符串包含一个或多个(m)个三个或更多(n)个元素的集合。

对于输入:"0,0,0 | 500,0,10 | 0,300,20 | 500,300,30"
我期望得到输出:double[][]{{0,0,0},{500,0,10},{0,300,20},{500,300,30}}

下面的代码清单有效,但是,我想要改进代码如下(我正在努力实现这一点):

  1. 使代码通用,适用于可变数量的n元素,使其可以接受类似于*"0,0,0 | 500,0,10 | 0,300,20,999 | 500,300,30"*的输入,其中output[2] = [0,300,20,999]。我目前使用(map(x -> new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])})),我想以通用方式重写它。
  2. 理想情况下,将这两个流表达式合并为一个表达式,在一次操作中从字符串获取并输出双重[m][n]。这可能吗?

代码清单:

	String ss = "0,0,0 | 500,0,10 | 0,300,20 | 500,300,30";
	System.out.println(ss);
	
	String[][] result_s = 
			Arrays.
			stream(ss.split("\\|")).
			map(x -> x.trim().split(",")).
			toArray(size -> new String[size][1]);
	double[][] result_d = 
			Arrays.stream(result_s).
			// 这下面一行是令人尴尬的部分,我想要使其通用化(不依赖元素数量)
			map(x -> new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])})
			.toArray(size -> new double[size][1]);
	
	double[][] result_new = Arrays.stream(ss.split("\\|")).collect(Collectors.toList(entry -> entry.x.trim().split(",")));
			Arrays.
			stream(ss.split("\\|")).
			map(x -> x.trim().split(",")).
			map(x -> new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])}).
			toArray(size -> new String[size][1]);
	
	// 字符串数组
	System.out.println("String arrays");
	for(String[] rs : result_s) System.out.println(Arrays.toString(rs));
	
	// 双重数组
	System.out.println("Double arrays");
	for(double[] rs : result_d) System.out.println(Arrays.toString(rs));

输出:

> 0,0,0 | 500,0,10 | 0,300,20 | 500,300,30<br>
> String arrays<br>
> [0, 0, 0]<br>
> [500, 0, 10]<br>
> [0, 300, 20]<br>
> [500, 300, 30]<br>
> Double arrays<br>
> [0.0, 0.0, 0.0]<br>
> [500.0, 0.0, 10.0]<br>
> [0.0, 300.0, 20.0]<br>
> [500.0, 300.0, 30.0]

英文:

As part of parsing a configuration string I would like to convert a string into a double[][] array. The configuration string contains one or more (m) sets of three or more (n) elements.

For the input: "0,0,0 | 500,0,10 | 0,300,20 | 500,300,30",
I would expect an output: double[][]{{0,0,0},{500,0,10},{0,300,20},{500,300,30}}

The listing below works, however, I would like to improve the code as follows (and I am having a hard time achieving that):

  1. Make the code generic, for a variable number of n-elements, such that it would accept an input such as "0,0,0 | 500,0,10 | 0,300,20,999 | 500,300,30", where the output[2] = [0,300,20,999]. I currently use (map(x -&gt; new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])})) which I want to rewrite generically.
  2. Ideally combine the two stream expressions into one expression, taking in the string and outputting the double[m][n] in one go. Is this possible?

Listing:

	String ss = &quot;0,0,0  | 500,0,10  |  0,300,20  | 500,300,30&quot;;
	System.out.println(ss);
	
	String[][] result_s = 
			Arrays.
			stream(ss.split(&quot;\\|&quot;)).
			map(x -&gt; x.trim().split(&quot;,&quot;)).
			toArray(size -&gt; new String[size][1]);
	double[][] result_d = 
			Arrays.stream(result_s).
			//This next line is the embarrassing part and I would like to make it generic (so independent of number of elements
			map(x -&gt; new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])})
			.toArray(size -&gt; new double[size][1]);
	
	double[][] result_new = Arrays.stream(ss.split(&quot;\\|&quot;)).collect(Collectors.toList(entry -&gt; entry.x.trim().split(&quot;,&quot;)));
			Arrays.
			stream(ss.split(&quot;\\|&quot;)).
			map(x -&gt; x.trim().split(&quot;,&quot;)).
			map(x -&gt; new double[]{Double.parseDouble(x[0]),Double.parseDouble(x[1]),Double.parseDouble(x[2])}).
			toArray(size -&gt; new String[size][1]);
	
	//Strings array
	System.out.println(&quot;String arrays&quot;);
	for(String[] rs : result_s) System.out.println(Arrays.toString(rs));
	
	//double array
	System.out.println(&quot;Double arrays&quot;);
	for(double[] rs : result_d) System.out.println(Arrays.toString(rs));

Output :

> 0,0,0 | 500,0,10 | 0,300,20 | 500,300,30<br>
> String arrays<br>
> [0, 0, 0]<br>
> [500, 0, 10]<br>
> [0, 300, 20]<br>
> [500, 300, 30]<br>
> Double arrays<br>
> [0.0, 0.0, 0.0]<br>
> [500.0, 0.0, 10.0]<br>
> [0.0, 300.0, 20.0]<br>
> [500.0, 300.0, 30.0]

答案1

得分: 1

首先,对于"尴尬的行",您可以逐个流式处理每个x,它是一个double[],并使用mapToDouble

.map(x -> Arrays.stream(x).mapToDouble(Double::parseDouble).toArray())

其次,这两个流可以非常简单地合并。在没有toArray(size -> new String[size][1])的情况下,第一个流是Stream<String[]>,这也是Arrays.stream(result_s)生成的内容。

toArray将流转换为数组,而Arrays.stream将数组转换为流,因此Arrays.stream(result_s)在某种程度上是在"撤销" toArray(size -> new String[size][1])的操作。这两行代码可以互相抵消。

double[][] result_d =
        Arrays.stream(ss.split("\\|"))
                .map(x -> x.trim().split(","))
                .map(x -> Arrays.stream(x).mapToDouble(Double::parseDouble).toArray())
                .toArray(double[][]::new);
英文:

First, for the "embarrassing line", you can stream each x, which is a double[], and mapToDouble:

.map(x -&gt; Arrays.stream(x).mapToDouble(Double::parseDouble).toArray())

Second, the two streams can be joined very simply. Without toArray(size -&gt; new String[size][1]), the first stream is Stream&lt;String[]&gt;, which is also what Arrays.stream(result_s) produces.

toArray converts the stream to an array, while Arrays.stream converts an array to a stream, so Arrays.stream(result_s) is kind of undoing what toArray(size -&gt; new String[size][1]) did. The two lines can cancel each other out.

double[][] result_d =
        Arrays.stream(ss.split(&quot;\\|&quot;))
                .map(x -&gt; x.trim().split(&quot;,&quot;))
                .map(x -&gt; Arrays.stream(x).mapToDouble(Double::parseDouble).toArray())
                .toArray(double[][]::new);

huangapple
  • 本文由 发表于 2020年10月3日 11:34:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/64180447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定