英文:
How to map a List of items 'n' times, but loop back to the beginning each time
问题
I'm fairly new to React, so there is probably just an easier way to do this.
But I have a List of items
```jsx
const NOTES = [
{ id: 0, val: "C" },
{ id: 1, val: "C#" },
{ id: 2, val: "D" },
{ id: 3, val: "D#" },
{ id: 4, val: "E" },
{ id: 5, val: "F" },
{ id: 6, val: "F#" },
{ id: 7, val: "G" },
{ id: 8, val: "G#" },
{ id: 9, val: "A" },
{ id: 10, val: "A#" },
{ id: 11, val: "B" },
];
The requirement is that a user will give a number of notes to display.
So for example, if the user gives 14 you would display
C, C#, D, D#, E, F, F#, G, G#, A, A#, B, C, C#
I currently have this
const keys = [...Array(13).keys()];
console.log("keys: ", keys);
return (
<div>
{keys.map((item) => (
<div key={item}>{NOTES[item % 12].val}</div>
))}
</div>
);
But because there are only 12 elements in the List, I get an error. Is there any way to make it so that when it reaches the last element in the List, I go back to the first element and continue 'n' times?
<details>
<summary>英文:</summary>
I'm fairly new to React, so there is probably just an easier way to do this.
But I have a List of items
const NOTES = [
{ id: 0, val: "C" },
{ id: 1, val: "C#" },
{ id: 2, val: "D" },
{ id: 3, val: "D#" },
{ id: 4, val: "E" },
{ id: 5, val: "F" },
{ id: 6, val: "F#" },
{ id: 7, val: "G" },
{ id: 8, val: "G#" },
{ id: 9, val: "A" },
{ id: 10, val: "A#" },
{ id: 11, val: "B" },
];
The requirement is that a user will give a number of notes to display.
So for example, if the user gives 14 you would display
C, C#, D, D#, E, F, F#, G, G#, A, A#, B, C, C#
I currently have this
const keys = [...Array(13).keys()];
console.log("keys: ", keys);
return (
<div>
{keys.map((item) => (
<div key={item}>{NOTES[item].val}</div>
))}
</div>
);
But because there are only 12 elements in the List, I get an error. Is there any way to make it so that when it reaches the last element in the List, I go back to the first element and continue 'n' times?
</details>
# 答案1
**得分**: 1
不要使用keys.map,可以创建一个函数。这个函数将接收一个参数(在这个示例中是需要的音符数量,例如14)。然后在函数内部声明NOTES数组,将计数器设置为0(作为变量),创建一个空数组,稍后要填充信息。定义一个循环,从0到你定义的参数。在循环内部执行数组的push操作,例如:myArray.push(NOTES0+网站访问量)。然后执行counter++操作。如果计数器等于11,则将其重新设置为0。然后在循环之外返回数组。然后将keys.map替换为myFunc(16).map,每个项将是你寻找的数组。希望这能帮助你找到正确的解决方案。
<details>
<summary>英文:</summary>
Instead of using keys.map
You can create a function
This function will receive a parameter (the number of times that you need notes in this example 14)
Then inside the func declare the NOTES array
Set a counter in 0 (let variable)
Set an empty array that you are going to fill with info after
Define a for loop that is going from 0 to the param that you defined
Inside for do an array.push
Example: myArray.push(NOTES0+网站访问量)
Execute counter++
If the counter is 11 set it to 0 again
Then outside for loop return the array
Then replace keys.map with myFunc(16).map
And each item will be the array that are you looking for
Hope this helps you to find the right solution
</details>
# 答案2
**得分**: 0
Jurgen的解决方案是正确的。
在过去,我曾因没有为我的数组指定类型而出现错误。
```javascript
var arr: string[] = [];
所以完整的解决方案应该是这样的:
var arr: string[] = [];
var c = 2;
for (var i = 0; i < numFrets; i++) {
arr[i] = NOTES[c].val;
c++;
if (c == 12) {
c = 0;
}
}
return (
<div>
{arr.map((item) => (
<div>{item}</div>
))}
</div>
);
英文:
In case anyone is stupid like me, Jurgen's solution is the way to go.
I got errors in the past due to now giving a type for my array.
var arr: string[] = [];
So the full solution would be something like this
var arr: string[] = [];
var c = 2;
for (var i = 0; i < numFrets; i++) {
arr[i] = NOTES[c].val;
c++;
if (c == 12) {
c = 0;
}
}
return (
<div>
{arr.map((item) => (
<div>{item}</div>
))}
</div>
);
答案3
得分: 0
你可以使用模数来回到数组的起始位置:
const NOTES = [{
id: 0,
val: "C"
},
{
id: 1,
val: "C#"
},
{
id: 2,
val: "D"
},
{
id: 3,
val: "D#"
},
{
id: 4,
val: "E"
},
{
id: 5,
val: "F"
},
{
id: 6,
val: "F#"
},
{
id: 7,
val: "G"
},
{
id: 8,
val: "G#"
},
{
id: 9,
val: "A"
},
{
id: 10,
val: "A#"
},
{
id: 11,
val: "B"
}
];
function getNoteSequence(numOfNotes) {
numOfNotes = numOfNotes || 0;
const totalNotesDefined = NOTES.length;
const result = [];
for (let currNote = 0; currNote < numOfNotes; currNote++) {
result.push(NOTES[currNote % totalNotesDefined]);
}
return result;
}
function generateHTML() {
const noteSequence = getNoteSequence(14);
document
.querySelector('#notes-container')
.innerHTML = noteSequence
.map((note) => `<div key="${ note.id }">${ note.val }</div>`)
.join('');
}
generateHTML();
<div id="notes-container"></div>
英文:
You can use modulo to loop back to the start of the array:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const NOTES = [{
id: 0,
val: "C"
},
{
id: 1,
val: "C#"
},
{
id: 2,
val: "D"
},
{
id: 3,
val: "D#"
},
{
id: 4,
val: "E"
},
{
id: 5,
val: "F"
},
{
id: 6,
val: "F#"
},
{
id: 7,
val: "G"
},
{
id: 8,
val: "G#"
},
{
id: 9,
val: "A"
},
{
id: 10,
val: "A#"
},
{
id: 11,
val: "B"
}
];
function getNoteSequence(numOfNotes) {
numOfNotes = numOfNotes || 0;
const totalNotesDefined = NOTES.length;
const result = [];
for (let currNote = 0; currNote < numOfNotes; currNote++) {
result.push(NOTES[currNote % totalNotesDefined]);
}
return result;
}
function generateHTML() {
const noteSequence = getNoteSequence(14);
document
.querySelector('#notes-container')
.innerHTML = noteSequence
.map((note) => `<div key="${ note.id }">${ note.val }</div>`)
.join('');
}
generateHTML();
<!-- language: lang-html -->
<div id="notes-container"></div>
<!-- end snippet -->
答案4
得分: 0
如Jurgen已经提到的,下面已经完成了相同的事情:
const NOTES = [
{ id: 0, val: "C" },
{ id: 1, val: "C#" },
{ id: 2, val: "D" },
{ id: 3, val: "D#" },
{ id: 4, val: "E" },
{ id: 5, val: "F" },
{ id: 6, val: "F#" },
{ id: 7, val: "G" },
{ id: 8, val: "G#" },
{ id: 9, val: "A" },
{ id: 10, val: "A#" },
{ id: 11, val: "B" },
];
const userInput = 14;
const keys = [...Array(13).keys()];
console.log("keys: ", keys);
const prepareFinalList = () => {
const finalListEl = [];
let userInputCounter = 0;
let i = 0;
// this userInput variable required to break the loop
while (userInputCounter <= userInput) {
if (i > NOTES.length - 1) {
i = 0;
}
const item = NOTES[i];
finalListEl[userInputCounter] = (<div key={item.id}>{item.val}</div>)
i++;
userInputCounter++;
}
// this will have the mapped dom structure
return finalListEl;
};
return (
<div>
{/*
1. instead of using map you should use different loop. Maybe normal for loop or while loop
and prepared your own Dom's array.
*/}
{prepareFinalList()}
</div>
);
英文:
As jurgen has already mentioned, the same thing has been done below:
const NOTES = [
{ id: 0, val: "C" },
{ id: 1, val: "C#" },
{ id: 2, val: "D" },
{ id: 3, val: "D#" },
{ id: 4, val: "E" },
{ id: 5, val: "F" },
{ id: 6, val: "F#" },
{ id: 7, val: "G" },
{ id: 8, val: "G#" },
{ id: 9, val: "A" },
{ id: 10, val: "A#" },
{ id: 11, val: "B" },
];
const userInput = 14;
const keys = [...Array(13).keys()];
console.log("keys: ", keys);
const prepareFinalList = () => {
const finalListEl = [];
let userInputCounter = 0;
let i = 0;
// this userInput variable required to break the loop
while(userInputCounter <= userInput) {
if (i > NOTES.length - 1) {
i = 0;
}
const item = NOTES[i];
finalListEl[userInputCounter] = (<div key={item.id}>{item.val}</div>)
i++;
userInputCounter++;
}
// this will have the mapped dom structure
return finalListEl;
};
return (
<div>
{/*
1. instead of using map you should use different loop. Maybe normal for loop or while loop
and prepared your own Dom's array.
*/}
{prepareFinalList()}
</div>
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论