답변:
사용할 수 있습니다 array_intersect()
.
$result = !empty(array_intersect($people, $criminals));
!empty
예상대로 작동하지 않는 것으로 나타났습니다 . 대신 다음을 사용했습니다 count()
.!count(array_intersect($people, $criminals));
array_intersect () 및 count () (비어있는 대신)를 사용하는 데 약간의 문제가 있습니다.
예를 들면 :
$bFound = (count(array_intersect($criminals, $people))) ? true : false;
count()
(당신은 즉, 마이크로 최적화 걱정하는 경우) 성능이 좋은 간주되지 않습니다
언어 구조로만 변수를 전달할 수 있으므로 해당 코드는 유효하지 않습니다. empty()
언어 구조입니다.
이 작업은 두 줄로해야합니다.
$result = array_intersect($people, $criminals);
$result = !empty($result);
in_array 대 array_intersect 성능 테스트 :
$a1 = array(2,4,8,11,12,13,14,15,16,17,18,19,20);
$a2 = array(3,20);
$intersect_times = array();
$in_array_times = array();
for($j = 0; $j < 10; $j++)
{
/***** TEST ONE array_intersect *******/
$t = microtime(true);
for($i = 0; $i < 100000; $i++)
{
$x = array_intersect($a1,$a2);
$x = empty($x);
}
$intersect_times[] = microtime(true) - $t;
/***** TEST TWO in_array *******/
$t2 = microtime(true);
for($i = 0; $i < 100000; $i++)
{
$x = false;
foreach($a2 as $v){
if(in_array($v,$a1))
{
$x = true;
break;
}
}
}
$in_array_times[] = microtime(true) - $t2;
}
echo '<hr><br>'.implode('<br>',$intersect_times).'<br>array_intersect avg: '.(array_sum($intersect_times) / count($intersect_times));
echo '<hr><br>'.implode('<br>',$in_array_times).'<br>in_array avg: '.(array_sum($in_array_times) / count($in_array_times));
exit;
결과는 다음과 같습니다.
0.26520013809204
0.15600109100342
0.15599989891052
0.15599989891052
0.1560001373291
0.1560001373291
0.15599989891052
0.15599989891052
0.15599989891052
0.1560001373291
array_intersect avg: 0.16692011356354
0.015599966049194
0.031199932098389
0.031200170516968
0.031199932098389
0.031200885772705
0.031199932098389
0.031200170516968
0.031201124191284
0.031199932098389
0.031199932098389
in_array avg: 0.029640197753906
in_array는 최소 5 배 더 빠릅니다. 결과가 발견되는 즉시 "중단"됩니다.
array_intersect()
.
isset
더 빠릅니다. 그리고 bool val을 사용하여 활성화하거나 비활성화 할 수 있습니다. 또한 키로 검색 값이 중복되지 않도록합니다. ´array_intersect 평균 : 0.52077736854553; in_array 평균 : 0.015597295761108; isset 평균 : 0.0077081203460693´
다음과 같이 in_array를 사용할 수도 있습니다.
<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
foreach($people as $num) {
if (in_array($num,$criminals)) {
$found[$num] = true;
}
}
var_dump($found);
// array(2) { [20]=> bool(true) [2]=> bool(true) }
array_intersect는 확실히 사용하기가 더 편리하지만 성능면에서 그다지 우수하지는 않습니다. 이 스크립트도 만들었습니다.
<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
$fastfind = array_intersect($people,$criminals);
var_dump($fastfind);
// array(2) { [1]=> int(20) [2]=> int(2) }
그런 다음 http://3v4l.org/WGhO7/perf#tabs 및 http://3v4l.org/g1Hnu/perf#tabs 에서 각각 두 스 니펫을 실행하고 각각 의 성능을 확인했습니다. 흥미로운 점은 총 CPU 시간, 즉 사용자 시간 + 시스템 시간이 PHP5.6에서 동일하고 메모리도 동일하다는 것입니다. PHP5.4의 총 CPU 시간은 약간은 아니지만 in_array의 경우 array_intersect보다 적습니다.
in_array
구현을 고수 할 것 입니다.
한동안 조사한 후에하는 방법입니다. 필드가 "사용 중"인지 확인하는 Laravel API 엔드 포인트를 만들고 싶었으므로 중요한 정보는 다음과 같습니다. 1) 어떤 DB 테이블입니까? 2) 어떤 DB 컬럼? 3) 해당 열에 검색어와 일치하는 값이 있습니까?
이를 알면 연관 배열을 구성 할 수 있습니다.
$SEARCHABLE_TABLE_COLUMNS = [
'users' => [ 'email' ],
];
그런 다음 확인할 값을 설정할 수 있습니다.
$table = 'users';
$column = 'email';
$value = 'alice@bob.com';
그런 다음 array_key_exists()
및 in_array()
서로를 사용 하여 1, 2 단계 콤보를 실행하고 truthy
조건에 따라 조치를 취할 수 있습니다.
// step 1: check if 'users' exists as a key in `$SEARCHABLE_TABLE_COLUMNS`
if (array_key_exists($table, $SEARCHABLE_TABLE_COLUMNS)) {
// step 2: check if 'email' is in the array: $SEARCHABLE_TABLE_COLUMNS[$table]
if (in_array($column, $SEARCHABLE_TABLE_COLUMNS[$table])) {
// if table and column are allowed, return Boolean if value already exists
// this will either return the first matching record or null
$exists = DB::table($table)->where($column, '=', $value)->first();
if ($exists) return response()->json([ 'in_use' => true ], 200);
return response()->json([ 'in_use' => false ], 200);
}
// if $column isn't in $SEARCHABLE_TABLE_COLUMNS[$table],
// then we need to tell the user we can't proceed with their request
return response()->json([ 'error' => 'Illegal column name: '.$column ], 400);
}
// if $table isn't a key in $SEARCHABLE_TABLE_COLUMNS,
// then we need to tell the user we can't proceed with their request
return response()->json([ 'error' => 'Illegal table name: '.$table ], 400);
Laravel 전용 PHP 코드에 대해 사과드립니다. 의사 코드로 읽을 수 있다고 생각하므로 남겨 두겠습니다. 중요한 부분 은 if
동 기적으로 실행되는 두 개의 문입니다.
array_key_exists()
그리고in_array()
PHP의 기능은 다음과 같습니다.
출처:
위에서 보여 드린 알고리즘의 좋은 점은 GET /in-use/{table}/{column}/{value}
(where table
,, are variables) column
와 같은 REST 끝점을 만들 수 있다는 것 value
입니다.
다음을 가질 수 있습니다.
$SEARCHABLE_TABLE_COLUMNS = [
'accounts' => [ 'account_name', 'phone', 'business_email' ],
'users' => [ 'email' ],
];
그런 다음 다음과 같은 GET 요청을 할 수 있습니다.
GET /in-use/accounts/account_name/Bob's Drywall
(마지막 부분을 uri 인코딩해야 할 수도 있지만 일반적으로 그렇지 않습니다)
GET /in-use/accounts/phone/888-555-1337
GET /in-use/users/email/alice@bob.com
누구도 할 수없는 일입니다.
GET /in-use/users/password/dogmeat1337
에 password
대해 허용 된 열 목록에이 (가) 나열되지 않았기 때문 입니다 user
.
당신의 여행에 행운을 빕니다.
$SEARCHABLE_TABLE_COLUMNS
! 이것은 주입을위한 비명을 지른다. 테이블과 열 문자열을 마스킹하고 필터링하는 "초 보안 프레임 워크 쿼리 빌더"가 있더라도 상관 없다! 끝 테이블과 열 문자열은 자리 표시 자 (준비된 문)를 통해 추가 할 수 없으며 SELECT ... FROM {$table} WHERE {$column} = :placeholder ....
. Ofc는 어댑터 (mysql, mongo, ...)에 의존하지만 저장할 인수가 아닙니다! Pls 정적 또는 목록 없음 =)