Метод skipWhile
у Laravel реалізує умовне фільтрування, пропускаючи елементи колекції, поки задана умова залишається істинною, а після цього включає всі залишкові елементи, як тільки умова перестає діяти
Метод послідовно оцінює кожен елемент, відкидаючи їх до тих пір, поки колбек не поверне значення false
:
$numbers = collect([5, 10, 15, 20, 25, 5, 10]);
$filtered = $numbers->skipWhile(function ($value) {
return $value < 20;
});
Якщо умова для будь-якого елемента стає хибною, цей елемент і всі наступні зберігаються, незалежно від того, чи задовольняють вони початкову умову
$scores = collect([45, 55, 65, 75, 85, 40, 90]);
$passingGrades = $scores->skipWhile(fn($score) => $score < 70);
Ось приклад системи обробки даних, що демонструє різні застосування skipWhile
:
class DataAnalysisService
{
public function processServerMetrics(Collection $metrics)
{
$criticalPeriod = $metrics->skipWhile(function ($metric) {
return $metric['cpu_usage'] < 80 && $metric['memory_usage'] < 85;
});
return $criticalPeriod->map(function ($metric) {
return [
'timestamp' => $metric['timestamp'],
'cpu_usage' => $metric['cpu_usage'],
'memory_usage' => $metric['memory_usage'],
'alert_level' => $this->calculateAlertLevel($metric),
'recommended_action' => $this->getRecommendedAction($metric)
];
});
}
public function analyzeUserBehavior(Collection $sessionData)
{
$engagementStart = $sessionData->skipWhile(function ($event) {
return in_array($event['action'], ['page_load', 'initial_scroll']) && $event['duration'] < 3;
});
$meaningfulInteractions = $engagementStart->filter(function ($event) {
return !in_array($event['action'], ['idle', 'background']);
});
return [
'engagement_start_time' => $engagementStart->first()['timestamp'] ?? null,
'total_meaningful_actions' => $meaningfulInteractions->count(),
'interaction_types' => $meaningfulInteractions->pluck('action')->unique()->values(),
'average_action_duration' => $meaningfulInteractions->avg('duration')
];
}
public function processFinancialTransactions(Collection $transactions)
{
$significantActivity = $transactions->skipWhile(function ($transaction) {
return abs($transaction['amount']) < 1000 && $transaction['type'] !== 'transfer';
});
$analysisResults = [
'first_significant_transaction' => $significantActivity->first(),
'total_volume' => $significantActivity->sum('amount'),
'transaction_count' => $significantActivity->count(),
'risk_indicators' => $this->identifyRiskPatterns($significantActivity)
];
return $analysisResults;
}
public function extractRelevantLogEntries(Collection $logEntries, string $incidentStart)
{
$incidentLogs = $logEntries->skipWhile(function ($entry) use ($incidentStart) {
return $entry['timestamp'] < $incidentStart || $entry['level'] === 'debug';
});
$categorizedLogs = $incidentLogs->groupBy('level');
return [
'error_count' => $categorizedLogs->get('error', collect())->count(),
'warning_count' => $categorizedLogs->get('warning', collect())->count(),
'critical_errors' => $categorizedLogs->get('error', collect())
->filter(fn($log) => str_contains($log['message'], 'CRITICAL'))
->values(),
'timeline' => $incidentLogs->take(50)->values()
];
}
public function processInventoryMovements(Collection $movements)
{
$stockCriticalPeriod = $movements->skipWhile(function ($movement) {
return $movement['quantity_after'] > 100 && $movement['movement_type'] !== 'emergency_restock';
});
$restockingAnalysis = $stockCriticalPeriod
->filter(fn($movement) => $movement['movement_type'] === 'restock')
->map(function ($restock) {
return [
'product_id' => $restock['product_id'],
'restock_quantity' => $restock['quantity_change'],
'time_to_restock' => $this->calculateRestockTime($restock),
'supplier' => $restock['supplier_name']
];
});
return [
'critical_period_start' => $stockCriticalPeriod->first()['timestamp'] ?? null,
'low_stock_duration' => $this->calculateDuration($stockCriticalPeriod),
'restock_events' => $restockingAnalysis->values(),
'average_restock_time' => $restockingAnalysis->avg('time_to_restock')
];
}
public function analyzeSalesPerformance(Collection $salesData)
{
$growthPeriod = $salesData->skipWhile(function ($sale) {
return $sale['daily_revenue'] <= $sale['previous_day_revenue'] || $sale['growth_rate'] < 0.05;
});
if ($growthPeriod->isEmpty()) {
return ['status' => 'no_growth_period_found'];
}
$performanceMetrics = $growthPeriod->map(function ($day) {
return [
'date' => $day['date'],
'revenue' => $day['daily_revenue'],
'growth_rate' => $day['growth_rate'],
'customer_acquisition' => $day['new_customers'],
'conversion_rate' => $day['conversion_rate']
];
});
return [
'growth_start_date' => $growthPeriod->first()['date'],
'peak_revenue_day' => $performanceMetrics->sortByDesc('revenue')->first(),
'average_growth_rate' => $performanceMetrics->avg('growth_rate'),
'total_new_customers' => $performanceMetrics->sum('customer_acquisition'),
'growth_consistency' => $this->calculateGrowthConsistency($performanceMetrics)
];
}
private function calculateAlertLevel($metric)
{
if ($metric['cpu_usage'] > 95 || $metric['memory_usage'] > 95) {
return 'critical';
}
if ($metric['cpu_usage'] > 85 || $metric['memory_usage'] > 90) {
return 'high';
}
return 'medium';
}
private function getRecommendedAction($metric)
{
return match($this->calculateAlertLevel($metric)) {
'critical' => 'Необхідне термінове втручання',
'high' => 'Масштабування ресурсів або оптимізація процесів',
'medium' => 'Постійно моніторити',
default => 'Продовжуйте моніторинг'
};
}
private function identifyRiskPatterns($transactions)
{
$patterns = [];
if ($transactions->where('amount', '>', 10000)->count() > 3) {
$patterns[] = 'висока_концентрація_сум';
}
if ($transactions->where('type', 'international')->count() > 5) {
$patterns[] = 'незвична_міжнародна_діяльність';
}
return $patterns;
}
}
Метод skipWhile
особливо ефективний у виявленні точок переходу в послідовних даних, що робить його ідеальним для аналізу часових рядів, виявлення порогів та фільтрацій на основі стану