I am trying to remove duplicate items from a collection that I request via an API in Laravel.
This is my code:
computed: {
// slice the array of data to display
filteredList() {
/* NEW PART */
var tips = this.dublicate;
/* END NEW PART */
tips = this.items.filter(item => {
return item.tip.toLowerCase().includes(this.search.toLowerCase())
})
return tips.slice(0, this.display);
},
dublicate() {
var filtered_array = [];
for(var i =0; i < this.items.length; i++) {
if(this.items[i].tip.toLowerCase() != this.items[i+1].tip.toLowerCase()) {
filtered_array.push(this.items[i])
}
}
return filtered_array;
}
}
}
If I remove the code within the NEW PART comments, everythin works fine.
In the NEW PART I am trying to remove duplicate content, based on the items tip attribute.
If the tip attribute is the same as the next items tip attribute, it should be excluded from the tips array, which is returned as a v-for="tips in filteredList".
However, I just get an empty array with this new part. What am I doing wrong?
I get the following from Vue Devtools:
dublicate:"(error during evaluation)"
filteredList:"(error during evaluation)"
An example data from items, that are from an API request:
(This is the data that I get, when I dont try to remove duplicates, which works)
As this is in VueJS, I cant use the answer provided here.
You are looking past the end of the array with i + 1. You need to push the last item without looking for the one after it (because there isn't one). I think using filter is more straightforward than building an array with a for loop.
dublicate() {
return this.items.filter((a, i) =>
i === this.items.length - 1 ||
a.tip.toLowerCase() !== this.items[i + 1].tip.toLowerCase()
);
}
Related
I have a snippet of code here where i have an array that may or may not have keys in it. When the user presses on a 'friend' they add them to a list (array) where they might start a chat with them (add 3 friends to the array, then start a chatroom). The users selected might be toggled on or off.
Current Behavior:
i can add/remove one person, but i cant add multiple people to the array at the same time. When i add one person, select another - the first person is 'active', when i remove the first person, the second person automatically becomes active
Expected Behavior:
I would like to be able to add multiple people to the array and then remove any of the selected items from the array
onFriendChatPress = (key) => {
console.log(key) // this is my key 'JFOFK7483JFNRW'
let friendsChat = this.state.friendsChat // this is an empty array initially []
if (friendsChat.length === 0) {
friendsChat.push(key)
} else {
// there are friends/keys in the array loop through all possible items in the array to determine if the key matches any of the keys
for (let i = 0; i < this.state.selGame.friends.length; i++) {
// if the key matches, 'toggle' them out of the array
if (friendsChat[i] === key) {
friendsChat = friendsChat.filter(function (a) { return a !== key })
}
else {
return friendsChat.indexOf(key) === -1 ? friendsChat.push(key) :
}
}
}
}
Help please!
From your code, I was quite confused regarding the difference between this.state.selGame.friends and this.state.friendsChat. Maybe I missed something in your explication. However, I felt that your code seemed a bit too overcomplicated for something relatively simple. Here's my take on that task:
class Game {
state = {
friendsChat: [] as string[],
};
onFriendToggle(key: string) {
const gameRoomMembers = this.state.friendsChat;
if (gameRoomMembers.includes(key)) {
this.state.friendsChat = gameRoomMembers.filter(
(member) => member !== key
);
} else {
this.state.friendsChat = [...gameRoomMembers, key];
}
}
}
I used typescript because it makes things easier to see, but your JS code should probably give you a nice type inference as well. I went for readability over performance, but you can easily optimize the script above once you understand the process.
You should be able to go from what I sent you and tweak it to be according to what you need
I built a custom component that filters an array of objects. The filter uses buttons, sets from active to non-active and allows more than one option on/off at the same time.
StackBlitz of my attempt - https://stackblitz.com/edit/timeline-angular-7-ut6fxu
In my demo you will see 3 buttons/options of north, south and east. By clicking on one you make it active and the result should include or exclude a matching "location" either north, south and east.
I have created my methods and structure to do the filtering, I'm struggling with the final piece of logic.
So far I have created a method to create an array of filtered locations depending on what the user clicks from the 3 buttons.
Next this passes to my "filter array" that gets the logic that should compare this filtered array against the original to bring back the array of results that are still remaining.
Its not quite working and not sure why - I originally got this piece of functionality working by using a pipe, but fore reasons do not want to go in that direction.
//the action
toggle(location) {
let indexLocation = this.filteredLocations.indexOf(location);
if (indexLocation >= 0) {
this.filteredLocations = this.filteredLocations.filter(
i => i !== location
);
} else {
this.filteredLocations.push({ location });
}
this.filterTimeLine();
}
// the filter
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
//the logic
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
https://stackblitz.com/edit/timeline-angular-7-ut6fxu
Sorry for my expression but u have a disaster in your code. jajaja!. maybe u lost that what u need but the logic in your functions in so wrong. comparing string with objects. filter a array that filter the same array inside... soo u need make a few changes.
One:
this.filteredLocations.push({location});
Your are pushing object. u need push only the string.
this.filteredLocations.push(location);
Two:
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
in this function you filter the timeLine array. and inside of contactMethodFilter you call filter method to timeLine again....
See a functional solution:
https://stackblitz.com/edit/timeline-angular-7-rg7k3j
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
This function is not returning any value and is passed to the .filter
Consider returning a boolean based on your logic. Currently the filter gets undefined(falsy) and everything would be filtered out
Note this is not a duplicate of How to extend an existing JavaScript array with another array, without creating a new array? because I'm looking to have a nested array, not to simply extend an array with another array to result into 1 array. Please read the question properly before you mark this as duplicate.
I'm looping through rows in a (Google) sheet to collect values, and would like to add each row as array to an array, which should result in an output like this (simplified example to illustrate):
array_main = [[row1_cell1,row1_cell2,row1_cell3], [row2_cell1,row2_cell2,row2_cell3], ...]
I first tried this with .push, which adds the values, but not as array:
accounts_last_row = 10
accounts_array = []
for (var i = 0; i < accounts_last_row; ++i) {
if ((accounts_range[i][1] == 'test') {
accounts_array.push([ [accounts_range[i][1]],[accounts_range[i][2]] ])
}
}
I'm aware similar questions have been asked, but most of them simply recommend using .concat to merge 2 arrays. I tried this as well but it doesn't add anything to the array:
...
if ((accounts_range[i][1] == 'test') {
accounts_array.concat( [accounts_range[i][1]],[accounts_range[i][2]] )
}
...
What am I missing? Thanks in advance.
You almost had it, inner arrays are simple ones, you had too many brackets.
Try like this:
accounts_array.push( [accounts_range[i][1],accounts_range[i][2]] );
the code above will work to add rows.
If you want to add data as a single column the you will have to change the brackets like this:
accounts_array.push( [accounts_range[i][1]],[accounts_range[i][2]] );
This type of operation can be done neatly with Array#filter and Array#push and apply:
const results = [];
const colIndexToTest = /** 0, 1, etc. */;
const requiredValue = /** something */;
SpreadsheetApp.getActive().getSheets().forEach(
function (sheet, sheetIndex) {
var matchedRows = sheet.getDataRange().getValues().filter(
function (row, rowIndex) {
// Return true if this is a row we want.
return row[colIndexToTest] === requiredValue;
});
if (matchedRows.length)
Array.prototype.push.apply(results, matchedRows);
});
// Use Stackdriver to view complex objects properly.
console.log({message: "matching rows from all sheets", results: results});
The above searches the given column of all rows on all sheets for the given value, and collects it into a 2d array. If all rows are the same number of columns, this array would be directly serializable with Range#setValues.
This code could have used map instead of forEach and the push.apply, but that would place empty or undefined elements for sheet indexes that had no matches.
I'm assuming if account-range[i][1] is 'test' copy the entire row to accounts_array. Drop the second index.
accounts_last_row = 10
accounts_array = []
for (var i = 0; i < accounts_last_row; ++i) {
if ((accounts_range[i][1] == 'test') {
accounts_array.push(accounts_range[i])
}
}
I am creating a questionnaire type form using ReactJs and Ant Design. It is a follow up question of How to create a questionnaire type form using Ant Design?
Now I am succeeded in adding new questions and their respective answers but not in removing them. Let's suppose I have added three questions and when I am trying to remove any one of them, its always removing the last one. The related code for removing is as follows:
remove = k => {
console.log(k);
const { form } = this.props;
// can use data-binding to get
const keys = form.getFieldValue("keys");
// We need at least one passenger
if (keys.length === 1) {
return;
}
keys.splice(k, 1);
// can use data-binding to set
form.setFieldsValue({
keys: keys
});
console.log(keys);
};
The complete code can be found as a demo on codesandbox.io.
I have done something similar in the past. Got rid of the boilerplate of antd's remove and replaced with this. Every time I add a row I push that row (object) to formRows array then removing like this:
remove = key => {
const newRows = this.state.formRows.filter(r => r.key !== key)
this.setState(
prev => ({
formRows: newRows
})
)
}
I'm new to javascript, and I'm trying to learn more about working with array's so I built a grocery list builder, and I'm getting stuck on reducing the list if the user accidentally inserts an item twice.
I think the problem is that my reducing function isn't hitting the item selector, but I haven't been able to find any examples showing this kind of problem.
This is what I have for a reducing function:
function reducingFood() {
var reducedFood = myGroceries.reduce(function(obj, item) {
var itemName = item['item'];
if(!obj[itemName]) {
obj[itemName] = 0;
}
obj[itemName]++;
return obj;
}, {})
addStructure();
}
I setup a JSFiddle showing the full code:
https://jsfiddle.net/Jon43/frvLc7Le/8/