I have a function called updateAnswer with multiple dynamic parameters.
updateAnswer(key, answer, array = false) {
if (array) {
if(this.answers.contains.find(element => element === answer)) {
//Delete item from array if already element already exists in this.answers.contains array.
} else {
Vue.set(this.answers, key, [...this.answers.contains, answer]);
}
} else {
Vue.set(this.answers, key, answer);
}
},
I'd like to know how delete an item in the array if the value already exists in the array.
You can use method called splice:
Just reference on your array and set values in the brackets the first is referenced on the position, the second is how many datas you want to splice/delete.
The function looks like this:
this.array.splice(value, value)
Lets see on an example - you have array food= [apple, banana, strawberry] than I'm using this.food.splice(1,1)..
my array looks now like this food = [apple, strawberry] - first value in my brackets are the position, the second one is the amount of "numbers" you want to delete.
Hopefully this helps you out!
I suppose each value in this.answers.contains is unique?
Anyways, if you just want to delete the item if already exists, I suggest filter(). It should look like below:
if(this.answers.contains.find(element => element === answer)) {
this.answers.contains = this.answers.contains.filter(c => c !== answer)
}
Also, the if condition if(this.answers.contains.find(element => element === answer)) could also be replaced by if(this.answers.contains.includes(answer))
Hope that could help you.
Related
I am trying to create a reactive filter for an array in Vue. My starting array comes from an API call which returns this.features (geojson features). I am filtering on a nested array. This works -- but when I enter a search term and then backspace back out to an empty string, and enter another string, I am not filtering the original array but appear to be filtering the already-filtered array. How could I filter again on the original array from the API call?
computed property:
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return feature.properties.site_observations.length > 0
})
return filtered
}
I have looked at Vue filtering objects property but I cannot make that code work (it uses Object.assign()). Thanks for any ideas.
Your computed property is mutating feature.properties.site_observations, that's a nono. Computed properties should be read only.
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
const site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return site_observations.length > 0
})
return filtered
}
It seems here is your problem:
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Because this code filter feature and alter the proprieties of feature.properties.site_observations. Then, in the next read the value is alter. We say that your function it is not pure, because it alter the state of feature.
So, what you should do is:
let anotherVariable = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Therefore, on a function, avoid alter state of objects, this lead to bugs.
On further checking, the above answer returns all site_observations, not just the ones that match the search. A much better solution is the following, using map to avoid overwriting the data, and the object spread operator to perform an object assign, and drilling down through the nested objects as follows:
filteredFeatures() {
return this.features
.map(feature => ({
...feature,
properties: {
site_observations: feature.properties.site_observations.filter(
element => {
return JSON.stringify(element).match(new RegExp(this.search, 'i'))
}
)
}
}))
.filter(feature => feature.properties.site_observations.length)
}
I have data stored in a state that is shown in flatlist, I want to sort the data based on ratings. So if I click on sort button they should be sorted in ascending order and when I click again, they should be sorted in descending order.
I have an array of objects stored in state, below is just a piece of data that is important.
show_data_list = [{ ratings : { overall : 4, ...other stuff } } ]
Is there a way I could do it, I tried using the map function which sorts array
list.map((a,b) => a-b)
But how can I use this to sort my array of objects, I cant pass in 2 item.rating.overall as the parameter.
Thanks in advance for the help :)
You can use javascript's built in sort function. You can provide a custom comparer function for it, which should return a negative value if the first item takes precedence, 0 if they are the same and a positive value if the second value should take precedence.
show_data_list.sort((a, b) => { return a.ratings.overall - b.ratings.overall; }). This will sort the data in the ascending order.
show_data_list.sort((a, b) => { return b.ratings.overall - a.ratings.overall; }). This will sort it in the descending order.
This is how I solved it stored the data in a variable and then sorted it based on condition
let rating = this.state.show_data_list;
rating.sort(function(a,b) {
return a.ratings.Overall < b.ratings.Overall
Try This
Sort your List Ascending/ Descending order with name or other string value in list
const [productSortList, setProductSortList] = useState(productarray);
where productarray is your main array
Ascending
productarray.sort((a, b) => a.products_name < b.products_name)
Descending
productarray.sort((a, b) => b.products_name < a.products_name),
You can reset the state of array you have passed as data in Flatlist
ascending ->
setProductSortList(
productarray.sort((a, b) => a.products_name < b.products_name),
);
do same for descending
How can we filter an ArrayList in Silverstripe 3?
where getVideosfromCategories() returns a merged ArrayList
I need something Like:
$this->getVideosfromCategories()->filter('ID:LessThan', $id)->sort(array('ID' => 'DESC'))->first()
these Filters (filter('ID:LessThan', $id)) only work with DataList ?
How can i filter my ArrayList?
these Filters (filter('ID:LessThan', $id)) only work with DataList ?
Yep, that's correct, search filter modifiers only work on DataList instances.
(https://docs.silverstripe.org/en/3/developer_guides/model/searchfilters/) It's interesting that the documentation does not mention that, I think it should be updated.
(I opened a PR for it https://github.com/silverstripe/silverstripe-framework/pull/9363)
But you can modify your current code to filter by an array of IDs instead, something like this:
$idsWeWant = [];
if ($id > 0) {
$idsWeWant = range(0, $id - 1); // "$id - 1" because you had "LessThan" modifier.
}
$this->getVideosfromCategories()
->filter('ID', $idsWeWant)
->sort(array('ID' => 'DESC'))
->first();
I am looping the rows within $.fn.dataTable.ext.search.push function to select some rows based on many criteria. I am setting some values on the TD of the tables known as orthogonal data. I am trying to get the value of the 'data-sort' but I don't know how. I am able to get the cell's inner data via data[2] (for column 2), but not the 'data-sort' or 'data-filter'. Any ideas?
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var iRating = parseFloat(data[2]) || 0; // this works
var datasort = //somehow get the data-sort from the TD
);
HTML
<td data-sort="57000" class=" seqNum">.....</td>
Looks like this way I can get the value. If there are any other better ways please advice:
$(settings.aoData[dataIndex].anCells[2]).data('sort')
Yes there is an easier way.
The data parameter is the "search data" for the row. i.e. the values for "filter" data for each col - not your "sort" data / anything else.
But you also have access to the full data object for the row i.e. the 4th parameter - rowData.
So you need to use rowData at the index of the column you want (you say 'for column 2', zero based so - 2 would be for the 3rd column).
Then you should find a property called 'sort' :
function(settings, searchData, index, rowData, counter){
var dataSort = rowData[1]['sort'];
console.log(`This should be the value you want : ${dataSort}`);
}
As per the documentation here
I have array of objects, objects have properties say "a", "b" and "c".
Now I need to filter out objects which has unique values of "a & b".
However c plays role on which objects to keep and which ones to reject.
If I do uniqBy on properties a and b, I will be blindly rejecting other objects. It will keep the first object it encounters in the array and reject all other duplicates.
Let me know if you need more clarification on the question.
This is how I found the uniq objects based on two properties.
var uniqArray= _.uniqBy(obj, function(elem) { return [elem.a, elem.b].join(); })
lodash uniq - choose which duplicate object to keep in array of objects
Do we have better solution?
Here is an example of input and expected output
Input: var arrayOfObj = [{a:1, b:1, c:2}, {a:1,b:1,c:1}, {a:2, b:2,c:2}];
Output: arrayOfObj = [{a:1,b:1,c:1}, {a:2, b:2,c:2}]; there should not be any duplicate a1,b1 combination
According to Lodash documentation, the order of result values is determined by the order they occur in the array. Therefore you need to order the array using the 'c' property in order to get the expected result.
To do so, you can use _.sortBy. It orders a collection in asc order based on a property or an iteratee. I think your problem could be solved using a property directly though you could use a function to provide a more accurate comparator if needed.
After that, you just perform the uniqBy action and retrieve the result:
var res = _(arrayOfObj)
.orderBy('c')
.uniqBy('a', 'b')
.value();
console.log(res);
Here's the fiddle.
As I read in the comments, your 'c' property is a timestamp. If you want to order from latest to newest, you can pass an iteratee to sort by in order to reverse the natural order by 'c':
var res = _(arrayOfObj)
.orderBy(function(obj) {
return -(+obj.c);
})
.uniqBy('a', 'b')
.value();
console.log(res);
You can check it out in this update of the previous fiddle. Hope it helps.
Would help to know what the actual data is and what you want to achieve with it. Here's an idea: group your objects based on a and b, then from each grouping, select one item based on c.
var arrayOfObj = [
{a:1, b:1, c:2},
{a:1, b:1, c:1},
{a:2, b:2, c:2}
];
var result = _.chain(arrayOfObj)
.groupBy(function (obj) {
return obj.a.toString() + obj.b.toString();
})
.map(function (objects) {
//replace with code to select the right item based on c
return _.head(objects);
}).value();