radash icon indicating copy to clipboard operation
radash copied to clipboard

[Feature Request-Object] PickBy

Open lveillard opened this issue 3 years ago • 14 comments

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)

lveillard avatar Nov 15 '22 16:11 lveillard

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>

sodiray avatar Nov 16 '22 16:11 sodiray

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}

lveillard avatar Nov 22 '22 12:11 lveillard

Funny, I call them filtero and mapo 🍻

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

sodiray avatar Nov 23 '22 00:11 sodiray

😂 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 avatar Nov 28 '22 17:11 lveillard

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 avatar Dec 02 '22 20:12 lveillard

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?

lveillard avatar Dec 06 '22 15:12 lveillard

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?

sodiray avatar Dec 12 '22 00:12 sodiray

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<T>

lveillard avatar Dec 13 '22 10:12 lveillard

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

prigaux avatar Jul 31 '23 11:07 prigaux

Any progress on this?

yubaoquan avatar May 02 '24 15:05 yubaoquan

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

aleclarson avatar Jul 09 '24 01:07 aleclarson

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

lveillard avatar Jul 09 '24 09:07 lveillard

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 avatar Jul 09 '24 22:07 aleclarson

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?

aleclarson avatar Jul 20 '24 18:07 aleclarson