将数组的String元素随机插入二维数组Java
Insert String elements of array into 2D array randomly Java
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
我想从 elements
创建一个二维 village
数组。在 howMany
数组中有元素出现的次数。如何将这些元素(最大值在 howMany
中)随机插入到二维数组中?
您可以持有一个 ArrayList,其中包含可以进入 村庄 的所有可能元素。
在你的例子中,列表看起来像这样:
someList = new ArrayList<String>();
for(int i = 0; i < elements.length; i++) {
for(int j = 0; j < howMany[i]; j++) {
someList.add(elements[i]);
}
}
有了这个,我们就有了一个包含所有可能元素的列表。现在我们将开始用我们的随机元素填充矩阵,一个一个地丢弃我们使用的每个元素。
Random rand = new Random();
int n;
for(int x = 0; x < village.length; x++)
for(int y = 0; y < village[0].length; y++)
n = rand.nextInt(someList.size());
village[x][y] = someList.get(n);
someList.remove(n);
}
}
显然,在我的示例中,您应该导入 Random 和 ArrayList。
这是一种方法。使用 java.util.Random 中的 Random class,简单地遍历每个元素,无论它在 howMany 中出现多少次,使用 while 循环遍历随机坐标,直到它到达一个没有还没满。用当前元素填充,然后继续。
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
Random rand = new Random();
for (int i = 0; i < elements.length; i++)
{
for (int j = 0; j < howMany[i]; j++)
{
int x = rand.nextInt(village[0].length);
int y = rand.nextInt(village.length);
while (village[y][x] != null)
{
x = rand.nextInt(village[0].length);
y = rand.nextInt(village.length);
}
village[y][x] = elements[i];
}
}
for (int i = 0; i < village.length; i++)
{
for (int j = 0; j < village[0].length; j++)
{
System.out.print(village[i][j]);
}
System.out.println();
}
这是另一种方法:
int arrSize = 3;
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[arrSize][arrSize];
int[] histogram = new int[arrSize];
for(int i = 0; i < arrSize; i++)
{
for(int j = 0; j < arrSize; j++)
{
boolean found_element = false;
while(!found_element)
{
int randIndex = getRandomNumber(0, arrSize);
if(histogram[randIndex] < howMany[randIndex])
{
village[i][j] = elements[randIndex];
histogram[randIndex]++;
found_element = true;
}
}
}
}
for(int i = 0; i < arrSize; i++)
{
for(int j = 0; j < arrSize; j++)
{
System.out.printf(village[i][j]);
}
System.out.println();
}
这里是 'getRandomNumber' 函数:
public static int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
如果您将 2D 3x3 数组视为 1D 1x9 数组,您可以使用 Collections.shuffle(list)
来获取其中的随机元素数。
- 用所有需要的元素(2x、3x、4x)填充 1x9 容器
- 随机播放 1x9 容器中的元素
- 将元素移动到 3x3 数组
演示:
public static String[][] generate3x3Village() {
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
//1. fill 1x9 array with all necessary elements
String[] tmp = new String[9];
int index = 0;
for (int i = 0; i < elements.length; i++) {
for (int j = 0; j < howMany[i]; j++) {
tmp[index++] = elements[i];
}
}
//2. shuffle
Collections.shuffle(Arrays.asList(tmp));
//3. convert 1x9 array to 3x3 array
for (int i = 0; i < tmp.length; i++) {
village[i / 3][i % 3] = tmp[i];
}
return village;
}
用法:
public static void showVillage(String[][] village) {
for (String[] row : village) {
System.out.println(Arrays.toString(row));
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; i++) {//lets see few villages
String[][] village = generate3x3Village();
showVillage(village);
System.out.println("-----------");
}
}
输出:
[, , ]
[, , ]
[, , ]
-----------
[, , ]
[, , ]
[, , ]
-----------
[, , ]
[, , ]
[, , ]
-----------
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
static void buildVillage(int[] howMany, String[] elements, String[][] village) {
List<Integer> flatElIds = IntStream.range(0, howMany.length)
.flatMap(i -> IntStream.range(0, howMany[i]).map(__ -> i)).boxed().collect(Collectors.toList());
Collections.shuffle(flatElIds);
String[] flatElements = flatElIds.stream().map(x -> elements[x]).toArray(String[]::new);
for (int i = 0, xs = village[0].length, ys = village.length; i < ys; i++)
village[i] = Arrays.copyOfRange(flatElements, i * xs, (i + 1) * xs);
}
我喜欢 and the .
以下是其主题的三个变体。这里没有大的突破,但也许很有趣。
record
Java 16 提供新的 records 功能。记录是编写 class 的一种简短方式,其主要目的是透明且不可变地传递数据。编译器隐式创建构造函数、getter、equals
& hashCode
和 toString
.
我们可以使用一条记录来配对输入对,将表情符号字符用作图标以及我们希望看到该字符出现的次数。与使用两个单独的数组作为输入相比,这使我们的意图更加清晰和明确。
请注意,记录可以在方法中本地定义。 (顺便说一下,从 Java 16 开始,接口和枚举也是如此。)
record EmojiCount ( String emoji , int count ) {}
将您的输入定义为 unmodifiable list。
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
使用流获取要生成的所有表情符号字符的计数。
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
Collections.nCopies
重复生成我们需要的所有表情符号字符。我们可以做一个List
for each kind of emoji, using Collections.nCopies
to fill each list. We join those lists into a master list. Then shake them up randomly by calling Collections.shuffle
.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
我们将这些生成的表情符号分布在我们村庄网格(我们的二维数组)的行和列中。我们只需要嵌套一对 for
循环,访问每一行,然后访问每一列。随着我们的进行,我们增加了一个索引号来移动我们的表情符号列表以放置在网格中。
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
对于二维数组中的每一行
最后,转储到控制台。请注意紧凑的 for
循环转储二维数组,使用此 for-each 语法:for ( String[] row : village )
.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
完整代码示例
将所有代码放在一起。
package work.basil.demo.village;
import java.util.*;
public class App
{
public static void main ( String[] args )
{
// Define the emoji characters we use as icons.
record EmojiCount( String emoji , int count ) {} // New record feature in Java 16. Compact way to write an immutable data-carrier class.
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count ).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
// Populate the village.
// Generate all the emoji icons.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
// Lay out the terrain.
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
// Dump to console.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
}
}
当运行.
emojis = [, , , , , , , , ]
[, , ]
[, , ]
[, , ]
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
我想从 elements
创建一个二维 village
数组。在 howMany
数组中有元素出现的次数。如何将这些元素(最大值在 howMany
中)随机插入到二维数组中?
您可以持有一个 ArrayList,其中包含可以进入 村庄 的所有可能元素。
在你的例子中,列表看起来像这样:
someList = new ArrayList<String>();
for(int i = 0; i < elements.length; i++) {
for(int j = 0; j < howMany[i]; j++) {
someList.add(elements[i]);
}
}
有了这个,我们就有了一个包含所有可能元素的列表。现在我们将开始用我们的随机元素填充矩阵,一个一个地丢弃我们使用的每个元素。
Random rand = new Random();
int n;
for(int x = 0; x < village.length; x++)
for(int y = 0; y < village[0].length; y++)
n = rand.nextInt(someList.size());
village[x][y] = someList.get(n);
someList.remove(n);
}
}
显然,在我的示例中,您应该导入 Random 和 ArrayList。
这是一种方法。使用 java.util.Random 中的 Random class,简单地遍历每个元素,无论它在 howMany 中出现多少次,使用 while 循环遍历随机坐标,直到它到达一个没有还没满。用当前元素填充,然后继续。
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
Random rand = new Random();
for (int i = 0; i < elements.length; i++)
{
for (int j = 0; j < howMany[i]; j++)
{
int x = rand.nextInt(village[0].length);
int y = rand.nextInt(village.length);
while (village[y][x] != null)
{
x = rand.nextInt(village[0].length);
y = rand.nextInt(village.length);
}
village[y][x] = elements[i];
}
}
for (int i = 0; i < village.length; i++)
{
for (int j = 0; j < village[0].length; j++)
{
System.out.print(village[i][j]);
}
System.out.println();
}
这是另一种方法:
int arrSize = 3;
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[arrSize][arrSize];
int[] histogram = new int[arrSize];
for(int i = 0; i < arrSize; i++)
{
for(int j = 0; j < arrSize; j++)
{
boolean found_element = false;
while(!found_element)
{
int randIndex = getRandomNumber(0, arrSize);
if(histogram[randIndex] < howMany[randIndex])
{
village[i][j] = elements[randIndex];
histogram[randIndex]++;
found_element = true;
}
}
}
}
for(int i = 0; i < arrSize; i++)
{
for(int j = 0; j < arrSize; j++)
{
System.out.printf(village[i][j]);
}
System.out.println();
}
这里是 'getRandomNumber' 函数:
public static int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
如果您将 2D 3x3 数组视为 1D 1x9 数组,您可以使用 Collections.shuffle(list)
来获取其中的随机元素数。
- 用所有需要的元素(2x、3x、4x)填充 1x9 容器
- 随机播放 1x9 容器中的元素
- 将元素移动到 3x3 数组
演示:
public static String[][] generate3x3Village() {
int[] howMany = {2, 3, 4};
String[] elements = {"", "", ""};
String[][] village = new String[3][3];
//1. fill 1x9 array with all necessary elements
String[] tmp = new String[9];
int index = 0;
for (int i = 0; i < elements.length; i++) {
for (int j = 0; j < howMany[i]; j++) {
tmp[index++] = elements[i];
}
}
//2. shuffle
Collections.shuffle(Arrays.asList(tmp));
//3. convert 1x9 array to 3x3 array
for (int i = 0; i < tmp.length; i++) {
village[i / 3][i % 3] = tmp[i];
}
return village;
}
用法:
public static void showVillage(String[][] village) {
for (String[] row : village) {
System.out.println(Arrays.toString(row));
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; i++) {//lets see few villages
String[][] village = generate3x3Village();
showVillage(village);
System.out.println("-----------");
}
}
输出:
[, , ]
[, , ]
[, , ]
-----------
[, , ]
[, , ]
[, , ]
-----------
[, , ]
[, , ]
[, , ]
-----------
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
static void buildVillage(int[] howMany, String[] elements, String[][] village) {
List<Integer> flatElIds = IntStream.range(0, howMany.length)
.flatMap(i -> IntStream.range(0, howMany[i]).map(__ -> i)).boxed().collect(Collectors.toList());
Collections.shuffle(flatElIds);
String[] flatElements = flatElIds.stream().map(x -> elements[x]).toArray(String[]::new);
for (int i = 0, xs = village[0].length, ys = village.length; i < ys; i++)
village[i] = Arrays.copyOfRange(flatElements, i * xs, (i + 1) * xs);
}
我喜欢
以下是其主题的三个变体。这里没有大的突破,但也许很有趣。
record
Java 16 提供新的 records 功能。记录是编写 class 的一种简短方式,其主要目的是透明且不可变地传递数据。编译器隐式创建构造函数、getter、equals
& hashCode
和 toString
.
我们可以使用一条记录来配对输入对,将表情符号字符用作图标以及我们希望看到该字符出现的次数。与使用两个单独的数组作为输入相比,这使我们的意图更加清晰和明确。
请注意,记录可以在方法中本地定义。 (顺便说一下,从 Java 16 开始,接口和枚举也是如此。)
record EmojiCount ( String emoji , int count ) {}
将您的输入定义为 unmodifiable list。
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
使用流获取要生成的所有表情符号字符的计数。
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
Collections.nCopies
重复生成我们需要的所有表情符号字符。我们可以做一个List
for each kind of emoji, using Collections.nCopies
to fill each list. We join those lists into a master list. Then shake them up randomly by calling Collections.shuffle
.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
我们将这些生成的表情符号分布在我们村庄网格(我们的二维数组)的行和列中。我们只需要嵌套一对 for
循环,访问每一行,然后访问每一列。随着我们的进行,我们增加了一个索引号来移动我们的表情符号列表以放置在网格中。
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
对于二维数组中的每一行
最后,转储到控制台。请注意紧凑的 for
循环转储二维数组,使用此 for-each 语法:for ( String[] row : village )
.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
完整代码示例
将所有代码放在一起。
package work.basil.demo.village;
import java.util.*;
public class App
{
public static void main ( String[] args )
{
// Define the emoji characters we use as icons.
record EmojiCount( String emoji , int count ) {} // New record feature in Java 16. Compact way to write an immutable data-carrier class.
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count ).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
// Populate the village.
// Generate all the emoji icons.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
// Lay out the terrain.
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
// Dump to console.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
}
}
当运行.
emojis = [, , , , , , , , ]
[, , ]
[, , ]
[, , ]