I want to sort an Array depending on a Boolean, but only if a second condition is true.
I can sort the Array by Boolean like this (I know you could also leave out the if part, but I wanted to see if it works like this.
posts = sortBy(posts, [function(post) {
if (post.featured_post === true) {
return post
}
}]);
But now I would like to add another condition:
posts = sortBy(posts, [function(post) {
if (post.featured_post === true && post.date >= today) {
return post
}
}]);
But this does not seem to work anymore. I get pretty random orders.
Maybe I also don't understand how to use the sortBy with a function, so some help is highly appreciated.
PS: I don't get any errors, it just does not sort correctly.
Cheers
Because of #gforce301 s question I realized that I never transformed the event date into a javascript Date object. By doing this:
const today = new Date().setHours(0,0,0,0)
posts = sortBy(posts, [function(post) {
const postDate = new Date(post.date).setHours(0,0,0,0)
if (post.featured_post && postDate >= today) {
return post
}
}])
I actually got the sortBy to work – even with branch statements. Good to have another example of how lodash's sortBy works.
Thanks for your help. Cheers
Your solution works a bit by random and I think it will be hard to understand / adapt.
What about this one?
import { get } from 'lodash/fp'
import { overEvery, sortBy, negate } from 'lodash'
const shouldBeFirst = overEvery(
get('featured_post'),
({ date }) => (new Date(date).setHours(0,0,0,0)) == (new Date().setHours(0,0,0,0))
)
const preSortedPosts = sortBy(posts, 'date')
const sortedPosts = [
...preSortedPosts.filter(shouldBeFirst),
...preSortedPosts.filter(negate(shouldBeFirst))
]
Related
in react-native, I am trying to add a simple filtering option on the top of my screen. Just like this one.
But the filter works only on the first hit. After the first, the new array resolves always as empty.
Could anyone tell me where/why is this code failing? Thanks a lot!
import { exercisesList } from '-utils/exercisesList'
const [items, setItems] = useState(exercisesList)
const handleFilter = (treatment = 'All') => {
console.log('FILTER-TREATMENTE---->', treatment)
let filteredList = exercisesList
if (treatment === 'All') {
setItems(exercisesList)
} else {
filteredList = items.filter((item) => item.treatment === treatment)
console.log('filteredList----->', filteredList)
setItems(filteredList)
}
}
I think it is because the second time that the function runs the items has the previous filteted list, not the full list and you are filtering the items array, not exercistsList
I know others answers solve the problem but I think we can expand on the issue a bit just to better understand what went wrong. It was happening because the filtering was being run directly on the state it was supposed to alter so when second run comes its running on previously filtered data that may or may not meet the filtering requirements. Some pseudo code below on how it should have been done
data -> filter(data) -> updateState(filteredData) -> repeat()
const handleFilter = (treatment = 'All') => {
console.log('FILTER-TREATMENTE---->', treatment);
let filteredList = [];
if (treatment === 'All') {
setItems(exercisesList);
} else {
filteredList = exercisesList.filter((item) => item.treatment === treatment);
console.log('filteredList----->', filteredList);
setItems(filteredList);
}
};
I am attempting to port an application that had used sequelize 3.30.4 and I'm updating to 6.13, I'm assuming some things have changed because I can't use string literals in a where clause, or so the debugger tells me.
That said, I've done some googling and have found some basic examples that make sense sure but I'm not entirely sure how to convert this string to a format acceptable for findAndCountAll to be happy.
I've attempted something like this, thinking it might at least point me in the right direction however it does not.
let attributes = ['id', 'name', 'locationId'];
let where = undefined;
let order = [['name', 'ASC']];
where = {
classroom: {
locationId: request.query.locationId
}
}
this is the line that did at one time work but no longer works.
where = `"classroom"."locationId" = ${request.query.locationId}`;
const classrooms = await model.classroom.findAndCountAll(_.assign({},
requestHelper.computePaginationObject(request.query.limit, request.query.page), {
attributes,
where: where ? [where] : undefined,
order
}));
how would I go about porting this into the proper format?
Try something like this:
let where = {}
if (<some condition>) {
where = {
locationId: request.query.locationId
}
}
const classrooms = await model.classroom.findAndCountAll(_.assign({},
requestHelper.computePaginationObject(request.query.limit, request.query.page), {
attributes,
where: where,
order
}));
You can also try that even if the first comment of ANATOLY works wonders :
const where = <some condition> ? {locationId: request.query.locationId} :{};
const classrooms = await model.classroom.findAndCountAll(_.assign({},
requestHelper.computePaginationObject(request.query.limit, request.query.page), {
attributes,
where,
order
}));
I know filter questions are covered extensivly on SO - but I'm struggling to implement my idea:
I want to filter through my panels & return an array filteredPanelTabItems for any that include the layouthint: "tab-view-item" and then the remainder of the array (without "tab-view-item") to another const so I can use it elsewhere, can anyone guide where I'm going wrong?
The screenshot above shows what's happening in the console when I log:
panel.panelLinks.links
const hasTabItemViewHint() => {
//check for string
}
const filteredPanelTabItems = panel.panelLinks.links.filter<Node>(
(panelLink) => panelLink.(call hasTabItemViewHint function?)
);
Consider something like this.
var filteredPanelTabItems = $.map(panel.panelLinks.links, function(l, i) {
if (l.LinkModal.layouthint._collections.indexOf("tab-view-item") >= 0) {
return l;
}
});
See more: https://api.jquery.com/jquery.map/
Edit 1
Shortened the code to
removeContentNew(i) {
var contents = this.state.templateContent;
contents.splice(i, 1);
this.setState({ templateContent: contents });
}
It might have something to do with this:
componentDidMount() {
this.setState({ templateContent: this.props.template.content });
}
Still removing the wrong one on screen. When I log the state, it does give me the right array though. Maybe something wrong with the map?
--
I'm trying to bug fix this piece of code but I can't seem to find the error.
removeContent(i) {
var $formgroup = false;
const regex = new RegExp('^content.', 'i'),
contents = _.reduce(_.keys(this.refs), (memo, k) => {
if (regex.test(k) && k !== 'content.' + i) {
var $formgroup = $(this.refs[k]);
if (this.props.customer.getSetting('wysiwyg_enabled', true)) {
var html = CKEDITOR.instances['html_' + i].getData();
} else {
var html = $formgroup.find('[name="html"]').val();
}
memo.push({
subject: $formgroup.find('[name="subject"]').val(),
html: html,
text: $formgroup.find('[name="text"]').val(),
language: $formgroup.find('[name="language"]').val()
});
}
return memo;
}, []);
this.setState({ templateContent: contents });
}
i is the ID of the item I want to remove from the array templateContents. Every time I press the remove button of one of the items it always seems to delete the last one and ignores the other ones.
I've been doing some testing with the k variable and that one might be the cause of the problems, but I am not sure at all.
I'm really quite new to the RegExp way of doing things.
Any ideas how I can fix this?
Update your state in the constructor instead of inside componentDidMount method.
constructor(pops) {
super(props);
this.state = {
templateContent: this.props.template.content
}
}
Also calls to setState are async so you don't have any security when the changes is being executed
The issue was in the mapping of the array. I'll leave this here because it helped me solve my issue.
Bad (Usually)
<tbody>
{rows.map((row, i) => {
return <ObjectRow key={i} />;
})}
</tbody>
This is arguably the most common mistake seen when iterating over an
array in React. This approach will work fine unless an element is
added or removed from the rows array. If you are iterating through
something that is static, then this is perfectly valid (e.g an array
of links in your navigation menu). Take a look at this detailed
explanation on the official documentation.
I am currently making an app using Firebase.
It is one of those bulletin boards that can be seen anywhere on the web.
But there was one problem.
This is a matter of date sorting.
I want to look at the recent date first, but I always see only the data I created first.
postRef.orderByChild('createData').startAt(reverseDate).limitToFirst(1).on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);
})
result - >hello1496941142093
My firebase tree
My code is the same as above.
How can I check my recent posts first?
How Do I order reverse of firebase database?
The Firebase Database will always return results in ascending order. There is no way to reverse them.
There are two common workaround for this:
Let the database do the filtering, but then reverse the results client-side.
Add an inverted value to the database, and use that for querying.
These options have been covered quite a few times before. So instead of repeating, I'll give a list of previous answers:
Display posts in descending posted order
Sort firebase data in descending order using negative timestamp
firebase sort reverse order
Is it possible to reverse a Firebase list?
many more from this list: https://www.google.com/search?q=site:stackoverflow.com+firebase+reverse%20sort%20javascript
You can simply make a function to reverse the object and then traversing it.
function reverseObject(object) {
var newObject = {};
var keys = [];
for (var key in object) {
keys.push(key);
}
for (var i = keys.length - 1; i >= 0; i--) {
var value = object[keys[i]];
newObject[keys[i]]= value;
}
return newObject;
}
This is how I solved it:
First I made a query in my service where I filter by date in milliseconds:
getImages (): Observable<Image[]> {
this.imageCollection = this.asf.collection<Image>('/images', ref => ref.orderBy('time').startAt(1528445969388).endAt(9999999999999));
this.images = this.imageCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Image;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
return this.images;
}
Then to get the newest date first I added this to my component where I call the method from my service:
let date = new Date;
let time = 9999999999999 - date.getTime();
console.log(time);
I pass the time let as the date. Since a newer date will be a bigger number to deduct from the 9999999999999, the newest date will turn up first in my query inside my service.
Hope this solved it for you
If you want to display it in the front end, I suggest that after you retrieve the data, use the reverse() function of JavaScript.
Example:
let result = postRef
.orderByChild("createData")
.startAt(reverseDate)
.limitToFirst(1)
.on("child_added", data => {
console.log(data.val().name + data.val().createData);
});
result.reverse();
Ive ended changing how I create my list on the frontend part.
was
posts.add(post);
changed to
posts.insert(0, post);
You could use a method where you save the same or alternate child with a negative value and then parse it.
postRef.orderByChild('createData').orderByChild('createData').on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);})
Far more easier is just use Swift's reversed():
https://developer.apple.com/documentation/swift/array/1690025-reversed
https://developer.apple.com/documentation/swift/reversedcollection
let decodedIds = try DTDecoder().decode([String].self, from: value)
// we reverse it, because we want most recent orders at the top
let reversedDecodedIds = decodedIds.reversed().map {$0}
orderBy("timestamp", "desc")
I think you can give a second argument name "desc".
It worked for me