题目
有一不定长的数组,里面存有的元素是字符串的形式,每个字符串包含运营商与 IP 地址的信息(用 -
分隔)。
我们希望每个运营商都有一个对应的颜色,即使每次重新运行,传入不同的数组,该颜色对应都不改变。
实现幂等性:相同的输入字符串总是产生相同的输出颜色。
输入:
js
let arr = [
"电信-111.123.321.22",
"移动-121.111.321.11",
"联通-123.123.321.33",
"ABC-133.123.321.44",
"ABC-144.123.321.55",
];
输出:
bash
[
{value:"电信-111.123.321.22",src:"电信",ip:"111.123.321.22",color:"#e5cfc5"},
{value:"移动-121.111.321.11",src:"移动",ip:"121.111.321.11",color:"#99f5d8"},
{value:"联通-123.123.321.33",src:"联通",ip:"123.123.321.33",color:"#aeefae"},
{value:"ABC-133.123.321.44",src:"ABC",ip:"133.123.321.44",color:"#da838b"},
{value:"ABC-144.123.321.55",src:"ABC",ip:"144.123.321.55",color:"#da838b"},
]
思路
-
先处理最简单的部分,将 ip 和 运营商 分割(使用
"".split()
函数)。 -
一开始我想着用 Map 来存储运营商与颜色的映射,但这样只要重新传入不同数组,颜色的对应就会改变,无法保证幂等性。
jslet arr = [ "电信-111.123.321.22", "移动-121.111.321.11", "联通-123.123.321.33", "ABC-133.123.321.44", "ABC-144.123.321.55", ]; let map = new Map(); // 此处逐个生成新颜色,简要编写非最终效果 let color = 0; function colorGen() { color += 10; return "#"+color; } let ans = arr.map((value) => { let [key, ip] = value.split("-"); let color = map.get(key); if (!color) { color = colorGen(); map.set(key, color); } return { value, src: key, ip, color, }; }); console.log(ans);
-
正确的实现方法是哈希,获取一个值将其映射为颜色
jslet arr = [ "电信-111.123.321.22", "移动-121.111.321.11", "联通-123.123.321.33", "ABC-133.123.321.44", "ABC-144.123.321.55", ]; // 经典DJB2哈希算法变种,生成一个哈希值 function hash(str) { let hashValue = 5381; // 初始质数(常用哈希种子) for (let i = 0; i < str.length; i++) hashValue = (hashValue << 5) + hashValue + str.charCodeAt(i); return hashValue; } // 将哈希值映射为颜色,颜色的 RGB 每一个位置都有两个十六进制数 function colorGen(key) { let hashValue = hash(key); let color = "#"; for (let i = 0; i < 3; i++) { const value = (hashValue >> (i * 8)) & 0xff; // 移位后取最右边 8 位 const adjust = 0x80 + (value % 0x80); // 限制在 128 到 255,避免过暗 color += adjust.toString(16).padStart(2, '0'); // 避免数字不够两位 } return color; } let ans = arr.map((value) => { let [key, ip] = value.split("-"); return { value, src: key, ip, color: colorGen(key), }; }); console.log(ans);