繁体   English   中英

如何改组键值对?

[英]how to shuffle key-value pairs?

我有一组值,需要时需要重新整理。 我不知道哪种变量类型最适合我。 数据实际上是基于键值结构的。

100 "white"
200 "black"
300 "red"

像那样 我想做的是根据我不知道的算法更改键值对,但是需要像这样对它们进行改组,但是改组不需要是随机的 ,因此我可以在需要时恢复数据。

100 "red"
200 "white"
300 "black"

我真的不知道我应该如何解决。 我应该使用HashTable之类的东西,如何动态地对其进行随机播放? 任何帮助表示赞赏

随机改组键值映射的另一种方法:

public static <K,V> void shuffleMap(Map<K,V> map) {
    List<V> valueList = new ArrayList<V>(map.values());
    Collections.shuffle(valueList);
    Iterator<V> valueIt = valueList.iterator();
    for(Map.Entry<K,V> e : map.entrySet()) {
        e.setValue(valueIt.next());
    }
}

编辑:

如果您不想更改原始地图(因为以后需要它),则可以创建一个新的地图:

public static <K,V> Map<K,V> shuffleMap(Map<K,V> map) {
    List<V> valueList = new ArrayList<V>(map.values());
    Collections.shuffle(valueList);
    Iterator<V> valueIt = valueList.iterator();
    Map<K,V> newMap = new HashMap<K,V>(map.size());
    for(K key : map.keySet()) {
        newMap.put(key, valueIt.next());
    }
    return newMap;
}

您并不是真的希望可以随机地恢复混合 (很快就会变得复杂),而只需保留原始地图即可。 如果不合适,则需要更好地描述您的问题。


好的,您想使用秘密密钥加密映射,提供另一个映射,然后再次对其解密。 显然,随机改组对此无济于事,甚至伪随机也无济于事,因为它没有提供可靠的改组方法。 在基本情况下,您的密钥将是我们映射的密钥之间的可逆映射。

public static <K,V> Map<K,V> encryptMap(Map<K,V> plainMap, Map<K,K> key) {
    Map<K,V> cryptoMap = new HashMap<K,V>(plainMap.size());
    for(Map.Entry<K,V> entry : plainMap.entrySet()) {
       cryptoMap.put(key.get(entry.getKey()), entry.getValue());
    }
    return cryptoMap;
}

实际上,解密仅在使用密钥的反向映射时才起作用。

因此,当您的示例密钥为{100, 200, 300} ,这些密钥的任何排列对于我们的“加密方案”都是有效的密钥。 (只有6种可能,这不是很安全。)

Map sampleKey = new HashMap<Integer, Integer>();
sampleKey.put(100, 200);
sampleKey.put(200, 300);
sampleKey.put(300, 100);

Map sampleUnKey = new HashMap<Integer, Integer>();
for(Map.Entry<Integer, Integer> e : sampleKey) {
   sampleUnKey.put(e.getValue(), e.getKey());
}

Map<Integer, String> data = new HashMap<Integer, String>();
data.put(100, "white");
data.put(200, "black");
data.put(300, "red");

System.out.println(data);

Map<Integer, String> encrypted = encryptMap(data, sampleKey);

System.out.println(encrypted);

Map<Integer, String> decrypted = encryptMap(data, sampleUnKey);

System.out.println(decrypted);

现在decrypted的地图应与原始地图相同。

对于更大的键集,您可能想要找到一种方案,以从一些可输入的键中获得合适的键排列。

我不确定您将如何精确地整理配对,但是如果您需要根据密钥来整理它们,可以使用Map

Map<String, String> map = new HashMap<String, String>();
map.put("100", "white");
map.put("200", "black");
map.put("300", "red");

// swap 100 with 200
String temp = map.get("100");
map.put("100", map.get("200"));
map.put("200", temp);

另外,如果您需要随机地洗钱对,您可以按照larsmans的建议创建一个Pair (基本上将存储一个int和一个String ),并将它们存储在一个数组中。 然后,可以使用稍作修改的Fisher-Yates shuffle版本。 遵循以下原则:

// initialize list
List<Pair<Integer, String>> values = new ArrayList<Pair<Integer, String>>();
values.add(new Pair<Integer, String>(100, "white"));
values.add(new Pair<Integer, String>(200, "black"));
values.add(new Pair<Integer, String>(300, "red"));

// shuffle
System.out.println(values); // e.g., [100 white, 200 black, 300 red]
Random random = new Random();
for (int i = values.size() - 1; i > 1; i--) {
    int j = random.nextInt(i + 1);
    // swap values between i-th Pair and j-th Pair
    Pair<Integer, String> iPair = values.get(i); // the iPair :-)
    Pair<Integer, String> jPair = values.get(j);
    String iString = iPair.getSecond();
    iPair.setSecond(jPair.getSecond());
    jPair.setSecond(iString);
}
System.out.println(values); // e.g., [100 red, 200 black, 300 white]

看来您需要一份清单。 地图就是这样。 但是,像HashMap这样的标准没有更改键和值之间关系的功能。

我想我会为此实现自己的地图。 创建一个实现java.util.Map的类,实现所需的方法,并创建其他一些用于“混合”的方法。

这完全取决于您在tupples列表上真正需要的功能。 您需要快速查找颜色吗? 可以有多个相同号的连音吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM