sodiray / radash

Functional utility library - modern, simple, typed, powerful
https://radash-docs.vercel.app
MIT License
4.19k stars 167 forks source link

[Feature Request-Object] PickBy #157

Open lveillard opened 1 year ago

lveillard commented 1 year ago

Hello! I was wondering if somebody is up to build this one

const root = {a: 2, b: 3, c: {d: 7}, e:8}
pickBy(root, ((x) => x>2) // result: {b:3, e:8}
pickBy(root, ((x) => x.d == 7) // result {c: {d: 7}}

is similar to array.find() but for objects

Smething like this:

const pickBy = (obj, fn) => Object.fromEntries(Object.entries(obj).filter(fn))
PickBy(root, ((k,v])=> v>2)
sodiray commented 1 year ago

Hey @lveillard 👋 I agree, being able to filter in a more dynamic way would be great! I'm hesitant to follow the path that lodash took. Honestly, the whole By suffix always confused me. What if we just call it filter?

const filter = <T>(
  obj: T,
  fn: (k: keyof T, v: T) => boolean
): Partial<T>
lveillard commented 1 year ago

Why not! I tend to call these oFilter, oMap... in order to make them obviously different to filter(), map()...

The o for "object" as they are object to object functions.

I always imagined these working natively like this:

{a:1, b:3}.filter((k,v)=>v>2)
// result: {b:3}
sodiray commented 1 year ago

Funny, I call them filtero and mapo 🍻

This is a pretty simple one, would you be interested in implementing it?

lveillard commented 1 year ago

😂 Now that i think about it, is just FilterEntries(), isnt? If we keep current naming logic 🤔

And right now i'm figthing against some deadlines but happy to collaborate after that!

lveillard commented 1 year ago

I'm struggling a bit with the Filter function's types but i added a find function. https://github.com/rayepps/radash/pull/178

For the filter i'm here:

export const oFilter = <RemovedKeys extends string, T extends Record<string|number|symbol,any>>(obj: T, fn: (k: keyof T, v:any)=>boolean):Omit<T, RemovedKeys> => Object.fromEntries(Object.entries(obj).filter(([k,v])=> fn(k,v)))

but i'm not there yet

lveillard commented 1 year ago
function OFilter<T, K extends keyof T>(obj: T, fn: (key: K, value: T[K]) => boolean): Pick<T, K> {
  return Object.fromEntries(Object.entries(obj).filter(([k,v]) => fn(k,v))) as Pick<T, K>;
}

What about this one?

sodiray commented 1 year ago

I think the return type you want is Partial<T>, I don't think you'll be able to type the specific keys that will be returned since it's dynamic at runtime.

Question, you're saying filter here but your PR says find. Did I miss something there?

lveillard commented 1 year ago

Yay, they are two different functions but im not sure about the naming.

Find gets only property and returns directly its value Filter shakes an object by a fn(k, v) and is the one that indeed could be typed as Partial

prigaux commented 1 year ago

For the record, radash shake can behave as lodash omitBy (which is alike pickBy, but inverted condition)

yubaoquan commented 4 months ago

Any progress on this?

aleclarson commented 2 months ago

Hello @lveillard, @yubaoquan, and @prigaux. Over at the Radashi fork, we've implemented pickBy inside of pick (see this PR). You can try it today by installing radashi@beta. See you over there!

https://github.com/radashi-org/radashi

lveillard commented 2 months ago

Hello @lveillard, @yubaoquan, and @prigaux. Over at the Radashi fork, we've implemented pickBy inside of pick (see this PR). You can try it today by installing radashi@beta. See you over there!

https://github.com/radashi-org/radashi

Thanks! What would be the difference vs using shake()? Also, does your fork include deep funtions or a way to generate them? Is the only key missing thing I would love to have here

aleclarson commented 2 months ago

What would be the difference vs using shake()?

It's the opposite of “shake with a callback”.

Some prefer this:

pick(obj, (value) => isWhatImLookingFor(value))

…over this:

shake(obj, (value) => !isWhatImLookingFor(value))

I guess it's mostly an opinion on what's more readable.

Also, a shake callback doesn't receive the object key (which should probably be fixed).

pick(obj, (value, key) => key !== 'foo' && value > 1)
aleclarson commented 1 month ago

Also, does your fork include deep funtions or a way to generate them? Is the only key missing thing I would love to have here

@lveillard Sorry, I missed this part in my previous reply. Would you mind opening a discussion here to get your thoughts out on this?