簡體   English   中英

將數組的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創建一個 2D village數組。 howMany數組中有元素出現的次數。 如何將這些元素(在howMany中具有最大值)隨機插入到二維數組中?

您可以持有 ArrayList 與村庄中所有可能的元素 go 。

在您的情況下,列表將如下所示:

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。

如果您將 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("-----------");
    }
}

Output:

[🌳, 🌳, 🏠]
[🌾, 🌳, 🌳]
[🏠, 🌾, 🌾]
-----------
[🌳, 🌾, 🌳]
[🌳, 🏠, 🌾]
[🌳, 🏠, 🌾]
-----------
[🌳, 🌳, 🏠]
[🏠, 🌾, 🌳]
[🌳, 🌾, 🌾]
-----------

這是一種方法。 使用 java.util.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' function:

public static int getRandomNumber(int min, int max) {
    return (int) ((Math.random() * (max - min)) + min);
}
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);
    }

我喜歡Aleksa答案和 Pshemo的答案。

以下是他們主題的三個變體。 這里沒有大的突破,但也許很有趣。

record

Java 16 提供了新的記錄功能。 記錄是編寫 class 的簡單方法,其主要目的是透明且不可變地通信數據。 編譯器隱式創建構造函數、getter、 equals & hashCodetoString

我們可以使用記錄來匹配輸入對,表情符號字符被用作圖標以及我們希望看到該字符的出現次數。 這使我們的意圖比使用兩個單獨的 arrays 作為輸入更加清晰和明確。

請注意,可以在方法中本地定義記錄。 (順便說一句,從 Java 16 開始,接口和枚舉也是如此。)

record EmojiCount ( String emoji , int count ) {}

將您的輸入定義為不可修改的列表

final List < EmojiCount > emojiCounts =
        List.of(
                new EmojiCount( "🏠" , 2 ) ,
                new EmojiCount( "🌾" , 3 ) ,
                new EmojiCount( "🌳" , 4 )
        );

使用 stream 獲取要生成的所有表情符號字符的計數。

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 ,使用Collections.nCopies來填充每個列表。 我們將這些列表加入到主列表中。 然后通過調用Collections.shuffle隨機搖動它們。

List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
    emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );

我們將這些生成的表情符號分布在我們村庄網格的行和列中,我們的二維數組。 我們只需要一對嵌套的for循環,以訪問每一行,然后是每一列。 當我們 go 時,我們增加一個索引號來移動我們要放置在網格中的表情符號列表。

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 = [🌳, 🌳, 🌳, 🏠, 🌾, 🌳, 🌾, 🌾, 🏠]
[🌳, 🌳, 🌳]
[🏠, 🌾, 🌳]
[🌾, 🌾, 🏠]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM