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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule proposal: prefer-array-find #730

Closed
oscarmarcelo opened this issue May 15, 2020 · 7 comments 路 Fixed by #735
Closed

Rule proposal: prefer-array-find #730

oscarmarcelo opened this issue May 15, 2020 · 7 comments 路 Fixed by #735

Comments

@oscarmarcelo
Copy link

Prefer .find() over .filter()[0], since find breaks the loop as soon as it finds a match.

Fail

const item = array.filter(x => x === '馃')[0];

Pass

const item = array.find(x => x === '馃');
@fisker
Copy link
Collaborator

fisker commented May 16, 2020

Fail

const item = array.filter(x => x === '馃').shift();

@sindresorhus
Copy link
Owner

Accepted. PR welcome.

@fisker fisker self-assigned this May 17, 2020
@fisker fisker changed the title Rule proposal: prefer-find Rule proposal: prefer-array-find May 18, 2020
@fisker
Copy link
Collaborator

fisker commented May 18, 2020

sindresorhus Asked about this in #735 (comment)

const result = array.filter(x => x === '馃');
const item = result[0];

To support this, we need check result not exported, and only accessed with [0]

  1. If we fix to
const result = array.find(x => x === '馃');
const item = result;

The name may confuse people const allTrueArray = array.filter(foo) -> const allTrueArray = array.find(foo) the allTrueArray is not an array anymore.

  1. If we fix to
const item = array.find(x => x === '馃');

problem is the item may in a loop, this will call .find() may times.

  1. If we support this, should we support
const result = array.filter(x => x === '馃');
const item = result.shift();
const result = array.filter(x => x === '馃');
const [item] = result;

too?

@oscarmarcelo What do you think?

@oscarmarcelo
Copy link
Author

Honestly, I don't understand the implications of the first two points, but I totally agree with the third one!

@fisker
Copy link
Collaborator

fisker commented May 21, 2020

I have one concern about side effects of .filter call, in this case

const arrayTypeObjects = foo.filter(object => {
	const isArray = Array.isArray(object.data);
	object.isArray = isArray; // <-- also add a mark to every object
	return isArray;
});

const firstArray = arrayTypeObjects[0];

doSomething(firstArray);

for (const object of foo) {
	if (object.isArray) { // <-- rely on the mark set above
		doSomething(object.data)
	} else {
		doSomethingDifferent(object.data)
	}
}

If we fix foo.filter to foo.find, the code will be broken.

For this reason, I suggest auto-fix under an option like this

{
	'unicorn/prefer-array-find': [
		'error',
		{
			ignoreSideEffect: true, 
			operatorForDefaultValueOfDestructuring: '??'
		}
	]
}

ignoreSideEffect

Default false, set to true enables auto fix.

operatorForDefaultValueOfDestructuring

Default undefined,

For this case

const [foo = bar] = array.filter(fn);

undefined

Suggest const foo = array.filter(fn) ?? bar and const foo = array.filter(fn) || bar, no auto fix.

nullish-coalescing-operator / ??

Auto fix to const foo = array.filter(fn) ?? bar

logical-or-operator / ||

Auto fix to const foo = array.filter(fn) || bar

//cc @sindresorhus @oscarmarcelo Thoughts?

@oscarmarcelo
Copy link
Author

Nice find! I didn't think about this to this level of detail! 馃槂
LGTM! 馃憤

@fisker
Copy link
Collaborator

fisker commented May 21, 2020

I thought this rule is easy too, actually it only took about 30 mins to finish the first implementation, then I dig more and more deeper...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants