Powershell, попытка эффективного сравнения наборов данных

У меня есть 2 набора данных. Set1 имеет примерно 129 тыс. строк, имеет столбец ID и, что немаловажно, код второго столбца, который мне понадобится позже. Set2 имеет только столбец ID. Set2 также содержит около 83 тысяч строк, и все они должны находиться в Set1. Оба файла/набора данных должны быть упорядочены по идентификатору, если это имеет значение. Оба должны быть строками, но все идентификаторы дополняются до 10 цифр.

  • Набор 1:
ID,Code
0000000002,0
0000012345,1
0000023456,0
0000056789,1
0000034567,0
0000078908,1
  • Набор 2:
0000000002
0000012345
0000056789
0000034567

Я пытаюсь найти все идентификаторы в наборе 1, которых нет в наборе 2, включая этот второй столбец для каждого идентификатора из набора данных 1. Мне также нужны все идентификаторы в наборе 1, которые находятся в наборе 2, включая этот второй столбец для каждого идентификатора.

Мне также нужны подмножества для каждого из них:

  1. Все идентификаторы в наборе 1, которых нет в наборе 2, включая этот столбец кода, разделенные кодом 0,1,2.

  2. Все идентификаторы в наборе Set1, которые находятся в наборе Set2, включая этот столбец кода, разделенные кодом 0,1,2.

Основные проблемы, с которыми я сталкиваюсь, заключаются в том, что наборы данных не совпадают: в основном наборе данных есть 2 столбца, а в наборе сравниваемых данных - только 1. И тот факт, что наборы данных настолько велики, что я пытаюсь сделать это эффективно, поэтому это не займет много времени, поскольку это ежедневная программа, и после того, как я получу эти списки подмножеств, нужно будет запустить и другие вещи.

  1. Я пытался импортировать массивы и сравнивать их, чтобы получить нужные мне наборы данных, но это занимает слишком много времени, чтобы быть практичным. Я говорю примерно 1 час+. это даже не доходит до того, что мне нужно подмножество их на основе 2-го столбца.

    $IDsNotIn2 = $Array1 | Where {$Array2 -NotContains $_}
    
  2. Я пытался использовать хеш-таблицы, но не смог заставить сравнения работать. Я импортировал CSV как хэш-таблицы. Затем называется Compare-Object. Ничего не вернули/ничего не показали при звонке.

    import-CSV -Path $FILE_LOC | ForEach-Object { $hashtable1[$_.ID] = $_.Code }
    
    import-CSV -Path $FIXED_FILE_LOC -Header ID | ForEach-Object { $hashtable2[$_.ID] }
    
    Compare-Object -ReferenceObject $hashtable1 -DifferenceObject $hashtable2 -Property ID -PassThru | ? {$_.SideIndicator -eq "< = "} | Select-Object -Property * -ExcludeProperty SideIndicator
    
    Compare-Object -ReferenceObject $hashtable1 -DifferenceObject $hashtable2
    
  3. Я попробовал .GetEnumerator и перебрал первую хеш-таблицу, и если ключ существует во второй, создал третью таблицу с новыми значениями. Но по какой-то причине все значения из первой таблицы помещаются в новую таблицу.

    $hashtable1.GetEnumerator() | ForEach-Object {
    IF (-Not ($hashtable2.ContainsKey($_.key))){
        $ID = $_.key
        $columncode = $_.value
        $ID_Not_in_First_File[$ID] = @{
         $Code= $columncode 
            }
        }
    }
    

Можете ли вы отредактировать копию вопроса, вставив буквальный образец обоих наборов, включая заголовки, если они есть?

Santiago Squarzon 07.08.2024 22:35

Я не могу привести буквальную выборку своих наборов данных, нет. Наборы данных точно такие же, как мой образец, который я включил в вопрос OG. Набор данных 1 — это CSV-файл с заголовками, такими как идентификатор, код, но в остальном он точно такой, как я туда вставил. 10-значные числа, запятая, а затем 0,1,2. Набор данных 2 представляет собой буквально 10-значное число в строке, без заголовков.

Zeke S 07.08.2024 22:43

да, теперь ясно, я имел в виду, что в вашем вопросе есть Set1= и Set2=, а затем в каждой строке есть пробелы, и я предполагаю, что это не так (пробелов нет). Это сбивает с толку читателей вашего вопроса.

Santiago Squarzon 07.08.2024 22:44

Хорошо, теперь я понимаю. Я использовал это как псевдокод, который на самом деле не означает ничего, кроме идентификации множеств. Я изменил это.

Zeke S 07.08.2024 22:51

В общем, я бы сделал хеш-таблицу одного из списков.

js2010 08.08.2024 16:31

Я пытался хешировать оба списка и сравнивать их. Но решение, которое предложил Сантьяго, заключалось в том, чтобы хешировать одно и перебирать другое, что помогло мне, и я смог использовать это для решения своей проблемы. Спасибо.

Zeke S 09.08.2024 22:23
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если я правильно понимаю, эффективным решением может быть следующее:

$mapNotInSet2 = @{}
$mapInSet2 = @{}
$rowsNotInSet2 = [System.Collections.Generic.List[object]]::new()
# NOTE: Use absolute path to the file here,
#       don't use relative path when calling a .NET method
$set2 = [System.Collections.Generic.HashSet[string]]::new(
    [System.IO.File]::ReadLines('path\to\set2.txt'))

$rowsInSet2 = foreach ($row in Import-Csv 'path\to\set1.csv') {
    # Id exists in Set 2
    if ($set2.Contains($row.Id)) {
        if (-not $mapInSet2.ContainsKey($row.Id)) {
            $mapInSet2[$row.Id] = [System.Collections.Generic.List[string]]::new()
        }
        $mapInSet2[$row.Id].Add($row.code)
        $row
        continue
    }

    # else, Id does not exist in Set 2
    if (-not $mapNotInSet2.ContainsKey($row.Id)) {
        $mapNotInSet2[$row.Id] = [System.Collections.Generic.List[string]]::new()
    }
    $mapNotInSet2[$row.Id].Add($row.code)
    $rowsNotInSet2.Add($row)
}

$rowsInSet2

Это даст 4 различных результата, используя образцы данных:

  • $rowsInSet2
ID         code
--         ----
0000000002 0
0000012345 1
0000012345 2
0000056789 1
0000034567 0
  • $mapInSet2 (подмножество, уникальные идентификаторы с соответствующими code)
Name                           Value
----                           -----
0000034567                     {0}
0000012345                     {1, 2}
0000056789                     {1}
0000000002                     {0}
  • $rowsNotInSet2
ID         code
--         ----
0000023456 0
0000078908 1
  • $mapNotInSet2 (подмножество, уникальные идентификаторы с соответствующими code)
Name                           Value
----                           -----
0000078908                     {1}
0000023456                     {0}

Спасибо за помощь. Я обнаружил одну ошибку в своем образце набора данных. Все идентификаторы должны быть уникальными в обоих списках. экв. В наборе 1 не должно быть 2 0000012345. Кроме того, я проверил ваш код и получил ошибку: if (-not $mapInSet2.ContainsKey($row.Id)) «Ключ не может быть нулевым», а также по адресу: $mapNotInSet2 [$row.Id].Add($row.code) "индекс массива имеет нулевое значение". У меня есть скриншот ошибки, но я не знаю, как его сюда разместить.

Zeke S 08.08.2024 16:03

Я просто запустил еще раз и поставил $row для печати прямо перед оператором if в foreach, и он ничего не распечатал. Я изменил его на «Write-Output $row», и ничего не распечаталось. Я не уверен, почему он пуст. Я использую локальные файлы и даже жестко запрограммировал прямой путь «C:\Temp\Z\имя_файла». Раньше я использовал import-csv для этого файла, и он работал нормально.

Zeke S 08.08.2024 16:10

Спасибо за помощь. Я обнаружил, что могу читать список set1 и перебирать его как обычно. Это исправило проблему, которую я видел. Это очень помогло. Еще раз спасибо.

Zeke S 09.08.2024 22:22

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