#php #arrays
#php #массивы
Вопрос:
У меня есть этот текущий PHP-массив
$newData =
array (size=3)
0 =>
array (size=6)
'company_name' => string 'CO 1' (length=32)
'year_and_filing_date' => string '2019' (length=4)
'total_revenue' => string '200' (length=3)
'net_income' => string '300' (length=3)
'net_cash_ending_balance' => string '150' (length=3)
'long-term_debt' => string '210' (length=3)
1 =>
array (size=6)
'company_name' => string 'CO 1' (length=32)
'year_and_filing_date' => string '2020' (length=4)
'total_revenue' => string '200' (length=3)
'net_income' => string '300' (length=3)
'net_cash_ending_balance' => string '150' (length=3)
'long-term_debt' => string '210' (length=3)
2 =>
array (size=6)
'company_name' => string 'CO 1' (length=32)
'year_and_filing_date' => string '2020' (length=4)
'total_revenue' => string '100' (length=3)
'net_income' => string '200' (length=3)
'net_cash_ending_balance' => string '50' (length=2)
'long-term_debt' => string '110' (length=3)
Я хочу объединить все массивы с аналогичными 'year_and_filling_date'
и суммировать все
свойства 'total_revenue'
, 'net_income'
, 'net_cash_ending_balance'
и 'long-term_debt'
Я не уверен, с чего начать,
Я подумываю о циклическом переходе к каждому массиву, чтобы получить уникальный ‘year_and_filing_date’
$unique_years = array_unique(
array_map(function($elem){
return $elem['year_and_filing_date'];
},
$newData)
);
результат ['2019','2020'];
А затем сделайте еще один цикл, чтобы отфильтровать $newData
результат ['2019','2020']
Я ожидаю получить два разных массива, один из которых возвращает 1 результат, а другой возвращает 2 результата,
Но как мне суммировать только выбранные поля?
Комментарии:
1. «Но как мне суммировать только выбранные поля?» Что вы имеете в виду как? Вы просто добавляете их вместе. Создайте новый пустой массив , выполните цикл по вашему
$newData
-array и проверьте, существует ли индекс значения вyear_and_filing_date
вашем новом массиве, если он не просто копирует выбранные значения, в противном случае добавьте их . Дополнительно: как вы получаете этот массив? Через базу данных? Возможно, вы могли бы вместо этого использовать групповые функции.
Ответ №1:
Вам не нужно фильтровать, вы можете проверить, существует ли запись с этим годом в цикле foreach
$result = [];
foreach ($newData as $row) {
$year = $row['year_and_filing_date'];
if(!isset($result[$year])) {
$result[$year]['total_revenue'] = $row['total_revenue'];
$result[$year]['net_income'] = $row['net_income'];
$result[$year]['net_cash_ending_balance'] = $row['net_cash_ending_balance'];
$result[$year]['long-term_debt'] = $row['long-term_debt'];
$result[$year]['last_scraped'] = date("Y-m-d h:i:s");
} else {
$result[$year]['total_revenue'] = $row['total_revenue'];
$result[$year]['net_income'] = $row['net_income'];
$result[$year]['net_cash_ending_balance'] = $row['net_cash_ending_balance'];
$result[$year]['long-term_debt'] = $row['long-term_debt'];
$result[$year]['last_scraped'] = date("Y-m-d h:i:s");
}
}
Ответ №2:
Это то, что я делал до сих пор, это работает, но не оптимизировано, я надеюсь, что кто-нибудь сможет улучшить мой код,
$newData = [];
/* Transform the Filling Date to Year */
array_walk($data,
function ($item2, $key) use (amp;$newData)
{
foreach($item2 as $keyAssoc => $val)
{
if($keyAssoc == 'year_and_filing_date')
{
if(!empty($val))
{
$newData[$key][$keyAssoc] = date("Y", strtotime(date("d/m/Y", strtotime($val))));
}
}else{
$newData[$key][$keyAssoc] = $val;
}
}
}
);
/* Group Data by Years and Sum Up */
if(count($newData)>0)
{
/* Get Unique Years */
$unique_years = array_unique(array_map(function($elem){return $elem['year_and_filing_date'];}, $newData));
asort($unique_years);
$consolidatedData = [];
foreach($unique_years as $key => $val)
{
foreach($newData as $k => $propertyName)
{
/* Compare if Year is Matching */
if($propertyName['year_and_filing_date'] == $val)
{
$filteredData = array_filter($consolidatedData, function ($item) use ($val){
return $item['year_and_filing_date'] === $val;
});
/* Already Exists */
if(count($filteredData)>0)
{
$consolidatedData[$val]['company_name'] = $propertyName['company_name'];
$consolidatedData[$val]['year_and_filing_date'] = $val;
$total_revenue_raw = $filteredData[$val]['total_revenue'] $propertyName['total_revenue'];
$consolidatedData[$val]['total_revenue'] = (string) $total_revenue_raw;
$net_income_raw = $filteredData[$val]['net_income'] $propertyName['net_income'];
$consolidatedData[$val]['net_income'] = (string) $net_income_raw;
$net_cash_ending_balance_raw = $filteredData[$val]['net_cash_ending_balance'] $propertyName['net_cash_ending_balance'];
$consolidatedData[$val]['net_cash_ending_balance'] = (string) $net_cash_ending_balance_raw;
$long_debt_raw = $filteredData[$val]['long-term_debt'] $propertyName['long-term_debt'];
$consolidatedData[$val]['long-term_debt'] = (string) $long_debt_raw;
$consolidatedData[$val]['source_url'] = $propertyName['source_url'];
$consolidatedData[$val]['last_scraped'] = date("Y-m-d h:i:s");
}else{
$consolidatedData[$val]['company_name'] = $propertyName['company_name'];
$consolidatedData[$val]['year_and_filing_date'] = $val;
$consolidatedData[$val]['total_revenue'] = $propertyName['total_revenue'];
$consolidatedData[$val]['net_income'] = $propertyName['net_income'];
$consolidatedData[$val]['net_cash_ending_balance'] =$propertyName['net_cash_ending_balance'];
$consolidatedData[$val]['long-term_debt'] = $propertyName['long-term_debt'];
$consolidatedData[$val]['source_url'] = $propertyName['source_url'];
$consolidatedData[$val]['last_scraped'] = date("Y-m-d h:i:s");
}
}
}
}
}
return var_dump($consolidatedData);
Ответ №3:
Небольшая модификация решения от alibek.gao.
Ввод:
$newData = [
['company_name' => 'CO 1' , 'year_and_filing_date' => '2019', 'total_revenue' => '200',
'net_income' => '300' , 'net_cash_ending_balance' => '150' , 'long-term_debt' => '210'
],
['company_name' => 'CO 1', 'year_and_filing_date' => '2020', 'total_revenue' => '200',
'net_income' => '300','net_cash_ending_balance' => '150', 'long-term_debt' => '210'
],
['company_name' => 'CO 1', 'year_and_filing_date' =>'2020', 'total_revenue' => '100',
'net_income' => '200', 'net_cash_ending_balance' => '50', 'long-term_debt' => '110',
]
];
Алгоритм можно легко записать в виде функции.
$aggregateSum = ['total_revenue','net_income','net_cash_ending_balance','long-term_debt'];
$groupBy = 'year_and_filing_date';
$result = [];
foreach ($newData as $row) {
$year = $row[$groupBy];
if(!isset($result[$year])) {
$result[$year] = $row;
} else {
foreach($aggregateSum as $field){
$result[$year][$field] = $row[$field];
}
}
}
В этом решении сохраняются не суммируемые поля:
Результат:
array (
2019 =>
array (
'company_name' => "CO 1",
'year_and_filing_date' => "2019",
'total_revenue' => "200",
'net_income' => "300",
'net_cash_ending_balance' => "150",
'long-term_debt' => "210",
),
2020 =>
array (
'company_name' => "CO 1",
'year_and_filing_date' => "2020",
'total_revenue' => 300,
'net_income' => 500,
'net_cash_ending_balance' => 200,
'long-term_debt' => 320,
),
)