I have a table. When I click on an element I return its index. How can I (starting from this element) display all elements with index + 9. i.e. if the selected element has index 0, then I also need to display elements with indexes 9, 18, 27, etc.
let newCell = [td#2, td#0, td#2, td#0, td#2, ..... td#1, td#0]
newCell.forEach((item, i) => {
item.addEventListener('click', () => {
console.log(i)
})
})
I have not included the code to "display" those elements that will come in the series, but below is the code that logs them out. You can update it to display them.
const DIFF = 9;
newCell.forEach((item, i) => {
item.addEventListener('click', ()=>logAllItemsInSeries(i));
}
const logAllItemsInSeries = (i) => {
console.log(i);
const series = [];
while (i < newCell.length) {
series.push(i);
i += DIFF;
}
series.forEach((index) => {
console.log(index);
console.log(newCell[index]);
});
};
What you need to do in this case is keep track of a count of what elements should be filtered out and then update that count as you filter through it. Unfortunately your cell data is unclear to me so I went ahead and made my own to explain.
let data = [];
for (let i = 0; i < 100; i++) {
data.push({ id: i });
}
function getByNine(id) {
let count = id + 9
return data.filter(i => {
if (i.id === count) {
count = count + 9
return i
} else {
return
}
})
}
console.log(getByNine(3))
Inside your event listener you would put a reference to the getByNine(i) function (or whatever you want to call it) and pass its index.
Inside this function you set a default count of 9 + whatever the id of the element clicked
Run a filter through your array of objects, when the count is correct return that item and then increment the count by 9 for the next correct element
function getByNine(i) {
// code here
}
newCell.forEach((item, i) => {
item.addEventListener('click', () => {
getByNine(i)
})
})
Related
This is just an exercise in a course, this app selects a random fruit from the fruits array and then the removeItem() function is supposed to remove that one from the array and returns the modified array, but I'm getting a weird output, and the function is not working.
The problem can be seen here
function randomFruit(importedArray) {
let random = Math.floor(Math.random() * importedArray.length);
return importedArray[random];
}
function removeItem(importedArray, item) {
for (let i = 0; i < importedArray.length; i++) {
if (importedArray[i] === item) {
importedArray.splice(i, 1);
return [...importedArray.slice(0, i), ...importedArray.slice(i + 1)];
} else {
return "not found";
}
}
}
function makeFruitArray() {
var foods = ["🍒", "🍉", "🍑", "🍐", "🍏"];
return foods;
}
let fruitArray = makeFruitArray();
let fruitItem = randomFruit(fruitArray);
let remaining = removeItem(fruitArray, fruitItem);
console.log({fruitArray, fruitItem, remaining});
There are two issues in the removeItem function -
If the random one is not the first item on the array, the function returns not found. It wouldn't run for the second loop at all, as your function returns not found after the first iteration.
The splice method updates the original array. While you are passing the fruitArray to the removeItem method, it gets passed as reference and updating it within the function using splice will update the actual array as well.
The simplest and safest way of removing an item from an array would be -
function removeItem(importedArray, item) {
const filteredArray = importedArray.filter((each) => each !== item);
if (filteredArray.length === 0) return 'Not Found';
return filteredArray;
}
There were two major problems:
Your for loop in removeItem was always returning on the first iteration
You were modifying the initial array as you removed items from it
I've also removed all the unnecessary code used to reproduce your problem. Please read How to Ask to make sure you are helping others help you.
function randomFruit(importedArray) {
let random = Math.floor(Math.random() * importedArray.length);
return importedArray[random];
}
function removeItem(importedArray, item) {
for (let i = 0; i < importedArray.length; i++) {
if (importedArray[i] === item) {
// Don't modify the original array since we want to
// display the original fruits
return [...importedArray.slice(0, i), ...importedArray.slice(i + 1)];
}
}
// Error condition goes outside the loop, not inside.
return null;
}
function makeFruitArray() {
var foods = ["🍒", "🍉", "🍑", "🍐", "🍏"];
return foods;
}
let fruitArray = makeFruitArray();
let fruitItem = randomFruit(fruitArray);
let remaining = removeItem(fruitArray, fruitItem);
console.log({fruitArray, fruitItem, remaining});
As himayan said, the issue was that splice already changes the array.
Here's my solution:
function removeItem(importedArray, item) {
for (let i = 0; i < importedArray.length; i++) {
if (importedArray[i] === item) {
importedArray.splice(i, 1);
break;
}
}
return importedArray;
}
Your remove item function is not working correctly. Instead of writing loops and splicing the array to create a new one you should just use the filter method
function removeItem(importedArray, item) {
let newArray = importedArray.filter(function (element) {
return element !== item;
});
return newArray;
}
I was working on a chart where i need my data to be sliced into small object based for better visibility. My array that i have is
{
"size":[
{
"timestamp":"1641329889000",
"size":12345,
"fees":123456,
"cost":168
},
{
"timestamp":"1641387032",
"size":456789,
"fees":4567891,
"cost":249
},
{
"timestamp":"1641435786",
"size":98765,
"fees":987654,
"cost":987
},
{
"timestamp":"1641435786",
"size":98765,
"fees":987654,
"cost":987
},
{
"timestamp":"1641435786",
"size":98765,
"fees":987654,
"cost":987
}
]
}
in which i want the array to be in this form
{
"size":{
"timestamp": ["1641329889000","1641387032","1641435786"],
"size": [12345,456789,98765],
"fees": [123456,4567891,987654],
"cost": [168,249,987]
}
}
i can achieve this using foreach and push like this
result.forEach(element => {
this.state.timestamp.push(element.timestamp);
this.state.size.push(element.size);
});
But i want this array to have the items only from the 10,20,30,40th index alone
I want not all the value. the values should be chosen only in the basis of x+10
Could anyone help me on this
Instead of forEach why not just use a for loop, and on the condition use the modulus % operator with 10? Like if (i % 10 == 0) inside of the for loop, or just increment i by 10 like i+=10.
You could take a for loop and a step for incrementing the index.
const
step = 10,
keys = ["timestamp", "size", "fees", "cost"],
result = Object.fromEntries(keys.map(k => [k, []]));
for (let i = 0; i < size.lenght; i += step) {
keys.forEach(key => result[key].push(size[i][key]));
}
Using forEach is a waste of resources.
You can use for instead:
for(let i=0;i<result.length;i+10){
this.state.timestamp.push(result[i].timestamp);
this.state.size.push(result[i].size);
}
For setting the state you should use setState not just push to it.
let tmp = {
...this.state
}
for(let i=0;i<result.length;i+10){
tmp.size.timestamp.push(result[i].timestamp);
tmp.size.push(result[i].size);
}
this.setState(tmp)
As mentioned by #cybercoder, you probably don't want to change the state variable within the forEach, as that will cause render to be called excessively.
You could simply use a counter and only push elements when the index is divisible by 10:
let i = 0;
let {timestamp, size} = this.state;
result.forEach(element => {
if (i % 10 === 0) {
timestamp.push(element.timestamp);
size.push(element.size);
}
i++;
});
this.setState({
...this.state,
timestamp,
size
});
If you do not want to include the very first (index 0) element:
let i = 0;
let {timestamp, size} = this.state;
result.forEach(element => {
// Exclude very first element
if (i % 10 === 0 && i !== 0) {
timestamp.push(element.timestamp);
size.push(element.size);
}
i++;
});
this.setState({
...this.state,
timestamp,
size
});
In the below code:
First I create an array of 10 elements
Next I remove 3 random elements from that array.
I try to add those 3 random elements into the original array in the original positions.
For some reason in step 3 above (in the FINAL ARR console log), the elements are being added in the wrong position. Is my slice function incorrect in step 3? If so, how do I modify it to be correct?
// Step 1. Create array of 10 elements
const originalValues = maxAmount => {
let finalArray = [];
for (let i = 0; i < maxAmount; i++) {
finalArray.push({
key1: `key1-${i+1}`,
position: i
});
}
return finalArray;
}
let finalArr = originalValues(10);
const finalArrOriginalLength = finalArr.length;
//Step 2. Remove 3 random elements in this case key1-2, key1-7, key1-8
const removedElements = [];
finalArr = finalArr.filter(elem => {
if (elem.key1 === 'key1-7' || elem.key1 === 'key1-2' || elem.key1 === 'key1-8') {
removedElements.push(elem);
return false;
} else {
return true;
}
});
/* Step 3. Add those 3 elements back to the original positions */
removedElements.forEach(elem => {
finalArr.splice(elem.position - (finalArrOriginalLength - finalArr.length) + 1, 0, elem);
});
/* The inserted elements from step 3 are being inserted in the wrong position as seen when this console.log prints out finalArr */
console.log('FINAL ARR', finalArr);
There's no need to subtract from elem.position.
If you sort the removed elements by the original positions, you should be able to insert them at those positions.
This assumes there haven't been any other changes to the array.
// Step 1. Create array of 10 elements
const originalValues = maxAmount => {
let finalArray = [];
for (let i = 0; i < maxAmount; i++) {
finalArray.push({
key1: `key1-${i+1}`,
position: i
});
}
return finalArray;
}
let finalArr = originalValues(10);
const finalArrOriginalLength = finalArr.length;
//Step 2. Remove 3 random elements in this case key1-2, key1-7, key1-8
const removedElements = [];
finalArr = finalArr.filter(elem => {
if (elem.key1 === 'key1-7' || elem.key1 === 'key1-2' || elem.key1 === 'key1-8') {
removedElements.push(elem);
return false;
} else {
return true;
}
});
/* Step 3. Add those 3 elements back to the original positions */
removedElements.sort((a, b) => a.position - b.position).forEach(elem => {
finalArr.splice(elem.position, 0, elem);
});
console.log('FINAL ARR', finalArr);
Try this...
// Step 1. Create array of 10 elements
const originalValues = maxAmount => {
let finalArray = [];
for (let i = 0; i < maxAmount; i++) {
finalArray.push({
key1: `key1-${i+1}`,
position: i
});
}
return finalArray;
}
let finalArr = originalValues(10);
const finalArrOriginalLength = finalArr.length;
//Step 2. Remove 3 random elements in this case key1-2, key1-7, key1-8
const removedElements = [];
finalArr = finalArr.filter(elem => {
if (elem.key1 === 'key1-7' || elem.key1 === 'key1-2' || elem.key1 === 'key1-8') {
removedElements.push(elem);
return false;
} else {
return true;
}
});
// Step 3. Add those 3 elements back to the original positions
removedElements
.sort((a,b)=>{return a.position > b.position ? 0 : 1 });
removedElements.forEach(elem => {
finalArr.splice(elem.position, 0, elem);
});
/* The inserted elements from step 3 are being inserted in the wrong position as seen when this console.log prints out finalArr */
console.log('FINAL ARR', finalArr);
I have a function "Next "that maps an array like in the example below and after incrementing the element I am doing something, but I also have another function "Prev" it pretty much does a similar mapping but in that function, I am decrementing the element. The Next function works fine but the Prev function doesn't, can someone please help me with this?
I am mapping an array of object
[
{
"id":"v82b3a65",
"name":"Name"
},
{
"id":"u0b26551",
"name":"Name2"
}
]
my functions :
const Next = () => {
array.items.map((item, key, element) => {
var next = element[key ++];
setId(next.id);
});
};
const Prev = () => {
array.items.map((item, key, element) => {
var prev = element[key --];
setId(prev.id);
});
};
render(
<View>
<Button title={'Prev'} onPress={Prev}/>
<Button title={'Next'} onPress={Next}/>
</View>
)
I am using those functions in onPress of buttons
The result I need: on Next button press I want it to set setID = next objects id and on Prev button press I want to set setID = previous object id
You should check index value if it is larger than 0 in Prev function. Also check if it is smaller than array length - 1 in Next function.
const Next = () => {
var newArray = myArray.map(function (value, index, elements) {
if (index < myArray.length - 1) {
var next = elements[index + 1];
// do something
}
});
};
const Prev = () => {
var newArray = myArray.map(function (value, index, elements) {
if (index > 0) {
var next = elements[index - 1];
// do something
}
});
};
I am trying to write a code with JS and React.
In the App.js file i have set the state for some components, like this:
class App extends Component {
state = {
leafs: [
{
id: "1",
percent: "",
win: false,
}
],
result: [
{
winProbability: "0",
}
]
};
It is possible to add many "leafs" and add a different "percent" in each of them. When a button is clicked, I want to multiply the percent (if it is true) with the percent in each "leaf". So if the percent is 3 in one leaf, 4 in another, and 5 in the last, I want the answer to be 60 (3*4*5).
Here is the function:
calculate = () => {
leafs: this.state.leafs.map(leaf => {
if (leaf.win === true) {
var sum = 1;
for (var i = 0; i < leaf.percent.length; i++) {
sum = sum * +leaf.percent[i];
}
console.log(sum);
this.setState({
result: this.state.result.map(result => {
result.winProbability = sum;
return result;
})
});
}
});
};
Whit the numbers as described above, the console shows 3 in one line, then 4, and then 5. So what am I doing wrong? I wold really appreciate som help!
This worked, but there is probably a better way:
calculate = () => {
var sum = [];
leafs: this.state.leafs.map(leaf => {
if (leaf.win === true) {
sum.push(leaf.percent);
}
});
var sumPrint = 1;
for (var i = 0; i < sum.length; i++) {
sumPrint = sumPrint * +sum[i];
}
this.setState({
result: this.state.result.map(result => {
result.winProbability = sumPrint;
console.log(sumPrint);
return result;
})
});
};
What you are looking for is a reduce function, instead of mapping. You are iterating over the array with map there and resetting the sum to 1 at the beginning of every iteration. I assume you want to achieve something like this:
calculate = () => {
this.setState({
result: Object.assign({}, this.state.result, {
winProbability: this.state.leafs.reduce(
(winProb, leaf) => (leaf.win ? winProb * leaf.percent : winProb),
1
)
})
});
};