![](/img/trans.png)
[英]Better way to map an array of objects to two arrays, one of unique keys and another of number of occurences
[英]Refining code: Is there a better way to map one (shorter) array to another (longer) array of objects in Javascript?
我有一个 React 项目,它使用一组 colors 来设置一些样式:
export const backlightArray = [
theme.capri,
theme.aqua,
theme.oceanGreen,
theme.yellow,
'orange',
theme.lightRed
];
和另一个具有锚标签属性的对象数组:
const siteStart = [
{ label: 'StackOverflow', href: 'https://stackoverflow.com' },
{ label: 'rwieruch', href: 'https://www.robinwieruch.de/blog' },
{ label: 'ITNext.io', href: 'https://itnext.io/' },
{ label: 'Dev.to', href: 'https://dev.to/' },
{
label: `ycombninator ('Hacker News')`,
href: 'https://news.ycombinator.com/'
},
{ label: 'OpenBase.io', href: 'https://openbase.io/' },
{ label: 'Coolors.co', href: 'https://coolors.co/' },
{ label: 'GitHub', href: 'https://www.github.com/' },
{ label: '/r/homelab/', href: 'https://www.reddit.com/r/homelab/' },
];
(我已经缩短了这个例子,但现在这个数组有 14 个链接)。
colors 数组比站点对象数组短。 我希望 colors 在 colors 阵列结束后重复,所以我想出了这个循环,从backlightArray
阵列中添加 colors 以获得siteStart
阵列的长度:
let siteListColorsArray = [];
for (let i = 0; i < siteStart.length; i++) {
if (siteListColorsArray.length < siteStart.length) {
backlightArray.map(color => siteListColorsArray.push(color));
}
}
然后是 map 那些 colors 以及链接的其他共享属性,如下所示:
const sites = siteStart.map((site, idx) => {
site.target = '_blank';
site.rel = 'noopener noreferrer';
site.id = `${site.label.slice(0, 3)}-${idx}`; // this is for 'key'
site.color = siteListColorsArray[idx];
return site;
});
export default sites;
我是这样写的,所以我可以在siteStart
数组中添加 /remove label
和href
对象,而不必弄乱已完成对象中的任何其他属性。
它工作正常,但我只是想知道:这段代码对其他人来说看起来不错吗? 如果你要做类似的事情,你会做哪些不同的事情?
我认为这应该为您完成工作:
colorsLastIndex = backlightArray.length - 1;
const sites = siteStart.map((site, idx) => {
const newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1 : idx;
site.id = `${site.label.slice(0, 3)}-${idx}`; // this is for 'key'
site.color = backlightArray[newIndex];
return site;
});
我得到了一个很好的答案,它替换了这个嵌套循环来创建一个更长的 colors 数组:
let siteListColorsArray = [];
for (let i = 0; i < siteStart.length; i++) {
if (siteListColorsArray.length < siteStart.length) {
/* lengths: (0) (13) */
backlightArray.map(color => siteListColorsArray.push(color));
/* (length = 6) (iterates until > 13) */
}
}
一旦索引大于 5 (backlightArray.length -1)
,使用此三元表达式从index % backlightArray.length
的模数中减去 1:
let colorsLastIndex = backlightArray.length - 1;
const sites = siteStart.map((site, idx) => {
site.id = `${site.label.slice(0, 3)}-${idx}`;
const newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1 : idx;
site.color = backlightArray[newIndex];
return site;
});
但是,此解决方案使newIndex
返回 -1,导致该迭代缺少颜色值。 当我使用console.log(newIndex)
时,你可以看到数字低于 0 并且没有返回到 5 - 我写了步骤来说明(我在控制台中执行了计算以验证):
/* start first iteration w/ index */
0
1
2
3
4
5
/* start newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1
(6) (6) (6) (5) (- 1) */
0 // 6 % 5 - 1
1 // 7 % 5 - 1
2 // 8 % 5 - 1
3 // 9 % 5 - 1
-1 // 10 % 5 - 1
0 // 11 % 5 - 1
1 // 12 % 5 - 1
2 // 13 % 5 - 1
这是对我有用的解决方案(注意: backlightArray.length
= 6):
const newIndex = idx >= backlightArray.length ? idx % backlightArray.length : idx;
site.color = backlightArray[newIndex];
console.log(newIndex):
/* start first iteration w/ idx */
0
1
2
3
4
5
/* start newIndex = (idx) >= backlightArray.length ? idx % backlightArray.length
(6) (6) (6) % (6) */
0 // 6 % 6
1 // 7 % 6
2 // 8 % 6
3 // 9 % 6
4 // 10 % 6
5 // 11 % 6
0 // 12 % 6
1 // 13 % 6
一旦索引达到 6,即 1 高于 5( backlightArray
中的最后一种颜色),6 = backlightArray.length
,则条件变为 true。 然后,索引除以 6 的余数等于 0,然后增加 1,直到索引达到另一个 6 倍数(例如 12),此时它再次变为 0。 这种情况也适用:
newIndex = idx + 1 > backlightArray.length ? idx % backlightArray.length : idx;
idx + 1
可能更能说明逻辑。
这是一个很好的模式,可以减少对笨拙的嵌套循环的需求。 非常感谢分享!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.