Записывать данные только в строку csv, не теряя предыдущие данные?

У меня есть стартовый CSV с примерами данных, например:

Underlying,AllBlue,AllRed
AUD,1/5/2024,
BRR,,
GBP, 3/10/2024,
CAD,,

Сегодня, 29.04.2024, с помощью другого процесса создается новый CSV, например, такой.

Underlying,AllBlue,AllRed
AUD,,
BRR,4/29/2024,
GBP,4/29/2024,
CAD,,4/29/2024

и я хочу добавить любые новые данные, найденные только в столбцах «AllBlue» и «AllRed», в исходный CSV. Желаемый результат будет

Underlying,AllBlue,AllRed
AUD,1/5/2024,
BRR ,4/29/2024,
GBP,4/29/2024,
CAD,,4/29/2024

Обратите внимание, как новые данные из CSV от 29 апреля 2024 г. перезаписываются в исходные. Кроме того, как ячейка GBP/AllBlue обновляется новой датой.


#sandbox testing
$CSVFiles = Get-ChildItem -Path "C:\Sandbox\test" -Filter "*.csv"
 
#put into array
$CSVData = @()

ForEach ($CSVFile in $CSVFiles) {
    $CSVContent = Import-Csv -Path $CSVFile.FullName 
    $CSVData += $CSVContent 
}
 
#output
$CSVData | Export-Csv -Path "C:\Sandbox\testoutput\colors.csv" -NoTypeInformation -Append

Это то, что я сейчас возвращаю.

"Underlying","AllBlue","AllRed"
"AUD","1/5/2024",""
"BRR","",""
"GBP","3/10/2024",""
"CAD","",""
"AUD","",""
"BRR","4/29/2024",""
"GBP","4/29/2024",""
"CAD","","4/29/2024"

Это добавляет данные, но не перезаписывает столбцы?. Я пробовал стирать несколько параметров, добавлять.

Были ли какие-либо попытки кодирования, которые вы уже пробовали? и если да, пожалуйста, добавьте это в свой вопрос

Santiago Squarzon 30.04.2024 02:33

Отправленные вами данные не являются содержимым каких-либо файлов CSV. Похоже, вы пытались воспроизвести то, как они отображаются в конкретном приложении, вместо того, чтобы открывать их в текстовом редакторе, а затем копировать и вставлять сюда. Пожалуйста, замените их, когда вы Редактируете свой вопрос, включив в него свой код и информацию об отладке.

Compo 30.04.2024 03:52

Пожалуйста, отредактируйте вопрос и скопируйте/вставьте вывод Get-Content -Path 'thefile.csv' в виде текста. Никаких фотографий.

lit 30.04.2024 04:24

вопрос: что ТОЧНО содержит НОВЫЙ CSV? содержит ли он все строки оригинала, но с НЕКОТОРЫМИ разными значениями? Содержит ли он НЕКОТОРЫЕ строки оригинала с НЕКОТОРЫМИ разными значениями?

sirtao 30.04.2024 08:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это один из способов получить желаемый результат. Встроенные комментарии должны помочь в мыслительном процессе.

# Import-Csv here instead
$sourceCsv = ConvertFrom-Csv @'
Underlying,AllBlue,AllRed
AUD,1/5/2024,
BRR,,
GBP, 3/10/2024,
CAD,,
'@

# Import-Csv here instead
$newCsv = ConvertFrom-Csv @'
Underlying,AllBlue,AllRed
AUD,,
BRR,4/29/2024,
GBP,4/29/2024,
CAD,,4/29/2024
ThisIsALineToAppend,,4/29/2024
'@

# create a hashtable using the Underlying property as keys
$map = $sourceCsv | Group-Object Underlying -AsHashTable

$linesToAppend = foreach ($line in $newCsv) {
    # if the Underlying value of the new Csv exists in the old CSV
    if ($map.ContainsKey($line.Underlying)) {
        # get the object having the same Underlying value of the old CSV
        $value = $map[$line.Underlying][0]
        # if the AllBlue of the new CSV is not null
        if (-not [string]::IsNullOrWhiteSpace($line.AllBlue)) {
            # update the object of the old CSV with this new value
            $value.AllBlue = $line.AllBlue
        }
        # if the AllRed of the new CSV is not null
        if (-not [string]::IsNullOrWhiteSpace($line.AllRed)) {
            # update the object of the old CSV with this new value
            $value.AllRed = $line.AllRed
        }

        # go to the next iteration
        continue
    }

    # else, this Underlying doesn't exist in the old CSV
    # so its gotta be appended
    $line
}

$sourceCsv + $linesToAppend | ConvertTo-Csv

Это работает так, как ожидалось. Большое спасибо за комментарии к сценарию Сантьяго. Это очень помогает.

iceman 30.04.2024 15:10

@iceman рад, что это было полезно. помните, что если это решит вашу проблему, вы можете принять ответ

Santiago Squarzon 30.04.2024 15:33

Это расширяет ответ @Santiago. Это позволит нескольким полям составлять составной ключ для каждой строки. Он также будет сравнивать все неключевые поля, не требуя их жесткого кодирования. Это несложно, если есть два (2) поля для сравнения. Гораздо сложнее, если нужно сравнить восемьдесят два (82) поля.

$NaturalKey = @('Underlying','New')

# Import-Csv here instead
$sourceCsv = ConvertFrom-Csv @'
Underlying,New,AllBlue,AllRed
AUD,9,1/5/2024,
BRR,8,,
GBP,7, 3/10/2024,
CAD,6,,
'@

# Import-Csv here instead
$newCsv = ConvertFrom-Csv @'
Underlying,New,AllBlue,AllRed
AUD,9,,
BRR,8,4/29/2024,
GBP,7,4/29/2024,
CAD,6,,4/29/2024
ThisIsALineToAppend,5,,4/29/2024
'@

# Compare the fields of both CSV files to ensure that they have the names.
# The fields do not need to be in the same order.
$SourceFields = $sourceCsv[0].psobject.Properties.name | Sort-Object
$NewFields = $newCsv[0].psobject.Properties.name | Sort-Object
if ($null -ne (Compare-Object -ReferenceObject $sourceFields -DifferenceObject $NewFields)) {
    Write-Error -Message 'CSV files do not have the same field names or number of fields."'
    return 1
}
# Only test for new values in the fields that are not part of the natural key.
$FieldsToCompare = foreach ($Field in $NewFields) { if ($Field -notin $NaturalKey) { $Field }}

# create a hashtable using the Underlying property as keys
$map = $sourceCsv | Group-Object $NaturalKey -AsHashTable -AsString

# Iterate over all rows of the new CSV file.
$linesToAppend = foreach ($line in $newCsv) {
    # Gather the fields comprising the natural key.
    $KeyValues = foreach ($k in $NaturalKey) { $line.$k }
    $Key = $KeyValues -join ', '
    # if the natural key value of the new Csv exists in the old CSV
    if ($map.ContainsKey($Key)) {
        # get the object having the same Underlying value of the old CSV
        $value = $map[$Key][0]
        # Iterate over the fields to be compared (all fields except those in the natural key).
        foreach ($Field in $FieldsToCompare) {
            # If the new field valus is not null or whitespace, replace the existing value.
            if (-not [string]::IsNullOrWhiteSpace($line.$Field)) {
                $value.$Field = $line.$Field
            }
        }
    } else {
        # else, this Underlying doesn't exist in the old CSV
        # so its gotta be appended
        $line
    }
}

$sourceCsv + $linesToAppend | ConvertTo-Csv

Другие вопросы по теме