将数组的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) 来获取其中的随机元素数。

  1. 用所有需要的元素(2x、3x、4x)填充 1x9 容器
  2. 随机播放 1x9 容器中的元素
  3. 将元素移动到 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 & hashCodetoString.

我们可以使用一条记录来配对输入对,将表情符号字符用作图标以及我们希望看到该字符出现的次数。与使用两个单独的数组作为输入相比,这使我们的意图更加清晰和明确。

请注意,记录可以在方法中本地定义。 (顺便说一下,从 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 = [, , , , , , , , ]
[, , ]
[, , ]
[, , ]