Eu uso a função fgetcsv() para dividir um arquivo .CSV em uma matriz para poder inserir os valores em um banco de dados.
O problema é que às vezes a corporação da qual eu baixo esses arquivos altera colunas em torno das quais altera o número do array. Aqui está um exemplo de um print_r do arquivo CSV:
Array ( [0] => Symbol [1] => Description [2] => Qty (Quantity) [3] => Price [4] => Price Chng % (Price Change %) [5] => Price Chng (Price Change ) [6] => Day Chng % (Day Change %) [7] => Day Chng (Day Change ) [8] => Cost Basis [9] => Gain % (Gain/Loss %) [10] => Gain (Gain/Loss ) [11] => Reinvest? [12] => Reinvest Capital Gains? [13] => Last Div (Last Dividend) [14] => Volume [15] => Security Type )
Array ( [0] => Test1 [1] => test desc [2] => 820 [3] => 19.505 [4] => -1.84% [5] => -0.365 [6] => -1.84% [7] => -300.37 [8] => 601.73 [9] => -18.4% [10] => -607.63 [11] => No [13] => 0.72025 [14] => 7041528 [15] => ETFs & Closed End Funds )
Array ( [0] => Test2 [1] => test desc again [2] => 110 [3] => 49.715 [4] => -1.83% [5] => -0.925 [6] => -1.76% [7] => -98.00 [8] => 95.2 [9] => -8.78% [10] => -526.55 [11] => Yes [14] => 28668328 [15] => ETFs & Closed End Funds )
Array ( [0] => Test3 [1] => test desc example [2] => 740 [3] => 21.71 [4] => -3.98% [5] => -0.9 [6] => -3.93% [7] => -657.59 [8] => 242.13 [9] => -20.63% [10] => -4176.73 [11] => No [13] => 2.0216 [14] => 2759846 [15] => ETFs & Closed End Funds )
Você pode ver que na segunda matriz há títulos como $column[0] é Símbolo e $column[3] é Preço.
[0] => Symbol [1] => Description [2] => Qty (Quantity) [3] => Price
Posso adicionar código para que $column[0] por exemplo sempre exiba o nome do símbolo? Se a corporação decidir adicionar uma coluna ou reorganizar as coisas, ela mudará a coluna Price para outra, como movê-la de $column[3] para $column[5]. Estou supondo que haja uma maneira de fazer com que ela pesquise qualquer chave que corresponda a uma coluna como Volume por exemplo, então qualquer chave que seja, ela poderia garantir que todas as chaves em cada matriz para Volume corresponderão a esse número de chave.
Eu estava apenas alterando manualmente os números da matriz quando eles fizeram isso, mas eles mudam muito, então estou pensando se posso adicionar algum código para onde a coluna Symbol seria sempre 0 e Price sempre estaria na coluna 3 e o mesmo se aplica a todos os nomes de coluna. Se eles forem reorganizados, eles ainda terão o mesmo número de antes?
Um pequeno exemplo do arquivo CSV:
"Symbol","Description","Qty (Quantity)","Price","Price Chng % (Price Change %)","Price Chng $ (Price Change $)","Day Chng % (Day Change %)","Day Chng $ (Day Change $)","Cost Basis","Gain % (Gain/Loss %)","Gain $ (Gain/Loss $)","Reinvest?","Reinvest Capital Gains?","Last Div (Last Dividend)","Volume","Security Type"
"Test1","ETF","820","$19.39","-2.42%","-$0.48","-2.42%","-$393.6","$601.73","-18.89%","-$3701.93","No","--","$0.72025","14,626,464","ETFs & Closed End Funds"
"Test2"," ETF","110","$49.43","-2.39%","-$1.21","-2.39%","-$133.1","$995.2","-9.31%","-$557.9","Yes","--","N/A","59,351,095","ETFs & Closed End Funds"
"Test3"," ETF","760","$21.77","-3.72%","-$0.84","-3.72%","-$638.4","$687.73","-20.02%","-$142.53","No","--","$2.0216","6,402,084","ETFs & Closed End Funds"
Na verdade, não é muita mágica, talvez a percepção do seu próprio histórico de tentativas (e erros) bloqueie um pouco sua mente.
Vamos ver se conseguimos mudar isso.
Primeiro, as boas notícias: especialmente com seu array, isso é simples, pois o arquivo CSV já foi analisado.
E tudo isso se resume a uma única função, array_keys() .
Bom!
Mas primeiro as coisas mais importantes. Vamos deixar claro que estamos falando de um array aqui:
Ok, talvez nenhuma novidade até agora. Mas é melhor prevenir do que remediar!
Agora, vamos deixar outra coisa clara: esta
$array
é uma lista :Uma lista significa que cada chave no array é um número inteiro consecutivo começando em zero. Ou seja, cada chave tem o valor da chave anterior mais um (+1 ou ++).
E se não houvesse uma chave anterior, esse número virtualmente anterior seria menos um (-1).
Um array sem membros é um exemplo de tal lista , assim como seria o valor de retorno de array("one") ou array("one", "two") etc.
Para matemáticos parece bem natural , eles só precisam especificar se o número zero faz parte de números naturais . Em PHP, o primeiro índice (chave) do array é sempre zero (0).
Então, falando sobre array_keys() aqui, para um array não vazio, podemos sempre dizer:
Ou para entender melhor array_keys() , pois ele retorna a lista de chaves:
Bom saber!
Mas chega de recursão array_keys() por enquanto e vamos dar uma olhada no panorama geral desse adorado array.
O dado
$array
é todo analisado em CSV, com o seguinte layout comum de um arquivo CSV:Este layout é baseado em linhas e
$array
há uma lista (veja acima) dessas linhas.Vamos primeiro obter o título, como ele é o primeiro na lista, podemos atribuí-lo com desconstrução de lista. Na verdade, parece atribuir a um array:
Agora, a próxima coisa é encontrar os SÍMBOLOS . Estamos procurando a primeira linha vazia.
Bom saber: array_keys() em ação para as chaves de valor .
E então tenho que admitir que te traí: não se trata apenas de array_keys() , há também array_slice() e array_shift() :
Ok, provavelmente está um pouco rápido agora, todas essas funções permanecem documentadas no manual do PHP em https://php.net/manual , portanto, reserve um tempo para ler se precisar. Você sempre pode continuar mais tarde aqui.
Vamos dar uma olhada no que temos até agora:
A saída já nos mostra como as chaves de símbolos correspondem às chaves de dados.
Se os de cada data puderem ser combinados com seu símbolo, você obtém o mapeamento e pode acessá-lo pelo nome ao lado do índice numérico.
Como cada símbolo (string) representará uma chave de array, os símbolos precisam ser verificados se estão se encaixando, por exemplo, um símbolo duplicado arruinaria o jogo. Virada de mesa:
Se isso for afirmado, podemos prosseguir e usar as chaves por símbolo (string) para obter o índice (inteiro). Caso não haja tal índice, podemos usar o operador de coalescência nulo e NULL como fallback.
Até agora para os arrays. No geral, funciona assim.
Naturalmente é possível resumir isso melhor, mas aí fica mais abstrato.
Por exemplo, eu pessoalmente prefiro a interface ArrayAccess para chaves simbólicas (aliasing de chave) e SplFileObject para valores separados por vírgula (CSV).
Pelo que me lembro, um exemplo que coloquei no Stackoverflow foi Process CSV Into Array With Column Headings For Key .
Se seus dados de entrada não forem estruturados de forma confiável, use uma lista de permissões de colunas esperadas na ordem desejada para filtrar e mapear os dados analisados. Demo >= PHP7.4 , Demo PHP7 - PHP8.3 , Demo PHP5.2 - PHP8.3
Conteúdo do arquivo:
Saída:
Você pode mapear dinamicamente posições de colunas usando a linha de cabeçalho. Primeiro, obtenha as posições de cabeçalho, depois use essas posições para acessar valores em cada linha.