Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(maxBy): Add maxBy function that select element that have max value by given condition in array #64

Merged
merged 10 commits into from
Jun 17, 2024

Conversation

l2hyunwoo
Copy link
Contributor

close #55

I added a function that select element that have max value by given condition in array.

스크린샷 2024-06-15 오후 10 55 08 스크린샷 2024-06-15 오후 10 55 21
  • If input array is not empty, return first element of array that have maximum value that satisfies given condition
  • If input array is empty, return undefined

Copy link

vercel bot commented Jun 15, 2024

@l2hyunwoo is attempting to deploy a commit to the Toss Team on Vercel.

A member of the Team first needs to authorize it.

* const result = maxBy(people, person => person.age);
* // result will be { name: 'Nunu', age: 30 }
*/
export function maxBy<T>(elements: T[], selector: (element: T) => number): T | undefined {
Copy link
Collaborator

@raon0211 raon0211 Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export function maxBy<T>(elements: T[], selector: (element: T) => number): T | undefined {
export function maxBy<T>(elements: T[], selector: (element: T) => number): T {

I believe returning undefined is stricter and less error-prone.

However, following TypeScript's convention that arr[0] is not nullable even if arr is empty (unless noUncheckedIndexedAccess is on) is also important for consistency -- that's why we chose sample to not return nullable even if it can return undefined.

For the sake of consistency, I believe we should not return undefined here.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, following TypeScript's convention that arr[0] is not nullable even if arr is empty

I tested this on TS Playground. And the result is below.

const array: number[] = [];
console.log(array[0]);

// [LOG]: undefined 

I think this log says it's null(or undefined) when point first element of empty array.

스크린샷 2024-06-17 오후 2 32 28

I think usage without undefined makes compilcated usecase. Let's see below example code.

When we use undefined

  const maxElement = maxBy<number>([]) ?? 0;

When we use Exception

let maxElement;
try {
  maxElement = maxBy<number>([]);
} catch (error) {
  // TODO: Logic when error occurred
}

const result = maxElement;

I think above one is more simple. What do you think?


But for the sake of consistency in this library, I also think it should not return undefined. Thanks for your advice.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Oh, what I thought was that here item is not nullable (in static types) even if array is empty.

Copy link
Collaborator

@raon0211 raon0211 Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I thought dealing with empty arrays is what users of es-toolkit have to handle in runtime...
(We do not check that the array is not empty using types)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see... It seems that usual convention in typescript. It's so hard to admit, but now I'm understand what you wrote. I'll change to non-nil type! Thanks for check it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After modification, all test cases pass well 👍🏻

Comment on lines 20 to 34
if (elements.length === 0) {
return undefined;
}
let maxElement = elements[0];
let max = selector(maxElement);

for (const element of elements) {
const value = selector(element);

if (value > max) {
max = value;
maxElement = element;
}
}

return maxElement;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (elements.length === 0) {
return undefined;
}
let maxElement = elements[0];
let max = selector(maxElement);
for (const element of elements) {
const value = selector(element);
if (value > max) {
max = value;
maxElement = element;
}
}
return maxElement;
let maxElement = elements[0];
let max = -Infinity;
for (const element of elements) {
const value = selector(element);
if (value > max) {
max = value;
maxElement = element;
}
}
return maxElement;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more readable I think. I'll fix it to this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It changed on this commit

@raon0211
Copy link
Collaborator

Thanks, @l2hyunwoo !

@codecov-commenter
Copy link

codecov-commenter commented Jun 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (3ecc062) to head (e4f8167).
Report is 382 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main       #64   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           49        50    +1     
  Lines          244       253    +9     
  Branches        27        28    +1     
=========================================
+ Hits           244       253    +9     

@raon0211 raon0211 merged commit 260bae9 into toss:main Jun 17, 2024
6 of 7 checks passed
@l2hyunwoo l2hyunwoo deleted the feature/#55 branch June 17, 2024 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for maxBy
3 participants