【问题标题】:Matching values in hash tables while ignoring case sensitivity betwen two CSV files匹配哈希表中的值,同时忽略两个 CSV 文件之间的大小写敏感性
【发布时间】:2016-03-23 06:15:58
【问题描述】:

我正在尝试通过查看 CSV 文件 2 中列的值是否包含在 CSV 文件 1 中来附加列。

我有一个 CSV 文件 1 (test1.csv):

csv1ColumnOne,csv1ColumnTwo
1,dF3aWv
2,
3,ka21p
4,NAE31
5,dsafl
6,nv02k
7,qng02
8,xcw3r
9,dF3aW

我有一个 CSV 文件 2 (test2.csv):

csv2ColumnOne,csv2ColumnTwo
bbetfe,DF3AW
asdf,dsafl
qwer,
zxcv,NAE31
poiu,nbrwp1

给定以下代码...

$hashTable = @()
Import-Csv C:\path\test1.csv | ForEach-Object {
  $hashTable[$_.csv1ColumnOne] = $_.csv1ColumnTwo
}

(Import-Csv C:\path\test2.csv) |
  Select-Object -Property *, @{n='csv1ColumnThree';e={
    if ($hashTable.ContainsKey($_.csv2ColumnTwo)) {
      $_.csv2ColumnTwo
    } elseif (-not ($_.csv2ColumnTwo)) {
      'No value found from csv file2'
    } else {
      'No value found from csv file1'
    }
  }} | Export-Csv "C:\path\testresults.csv" -NoType

结果如下所示:

csv2ColumnOne,csv2ColumnTwo,csv1ColumnThree
bbetfe,DF3AW,"No value found from csv file1"
asdf,dsafl,dsafl
qwer,,No value found from csv file2
zxcv,NAE31,NAE31
poiu,nbrwp1,"No value found from csv file1"

相反,它应该是这样的:

csv2ColumnOne,csv2ColumnTwo,csv1ColumnThree
bbetfe,DF3AW,dF3aW
asdf,dsafl,dsafl
qwer,,"No value found from csv file2"
zxcv,NAE31,NAE31
poiu,nbrwp1,"No value found from csv file1"

我之所以看到bbetfe,DF3AW,"No value found from csv file1" ins't bbetfe,DF3AW,dF3aW 是因为该值区分大小写。无论如何要忽略字母数字值的大小写敏感性?

【问题讨论】:

  • 注意,我不能使用-like,因为它会为csv1ColumnThree 列填充值dF3aWv 而不是dF3aW... Python 有类似 if (string.upper( ))。如果powershell有这样的东西那就太好了......

标签: csv powershell powershell-3.0


【解决方案1】:

ContainsKey() 的查找已经不区分大小写。您只是使用了错误的数据结构,并且以错误的方式使用它。

如果要在哈希表中查找 key,则需要实际使用要查找的数据作为哈希表的 key

$hashTable[$_.csv1ColumnTwo] = $_.csv1ColumnOne

要在哈希表的 中查找某些内容,请使用 ContainsValue()

但是,由于您只想检查第一个 CSV 的第二列是否包含来自第二个 CSV 的第二列的值,因此您首先不需要哈希表。一个简单的数组就足够了。

$list = Import-Csv 'C:\path\test1.csv' | Select-Object -Expand csv1ColumnTwo

Import-Csv 'C:\path\test2.csv' |
  Select-Object -Property *, @{n='csv1ColumnThree';e={
    if ($list -contains $_.csv2ColumnTwo) {
      $_.csv2ColumnTwo
    } elseif (-not ($_.csv2ColumnTwo)) {
      'No value found from csv file2'
    } else {
      'No value found from csv file1'
    }
  }} | Export-Csv 'C:\path\testresults.csv' -NoType

如果您不想在第二个 CSV 中“找到”空字符串,只需从 $list 中排除该元素:

$list = Import-Csv 'C:\path\test1.csv' |
        Select-Object -Expand csv1ColumnTwo |
        Where-Object { $_ }  # allow only non-empty values

不是每个问题都是钉子,所以不要试图用锤子解决所有问题。

【讨论】:

  • 我明白了,感谢我的更正。我同意锤子理论,但是当您没有首席开发人员或敏捷环境时,经理希望您在 10 分钟内做出更改并推出,我几乎没有时间进行重构/重新设计:(
  • 似乎有效,如果我想使用第一个文件中的值而不是将第二个值中的值复制到列csv1ColumnThree 怎么办?
  • 您可以使用哈希表将值从第一个 CSV 映射到自身 ($hashTable[$_.csv1ColumnTwo] = $_.csv1ColumnTwo),因此您可以使用查找 $hashTable[$_.csv2ColumnTwo],或者您可以像这样从数组中获取它:@ 987654330@.
  • 例如,value1(大写和小写)来自 file1,value2(仅大写)来自 file2。在代码中,我暂时将 value1 分配为大写,以便找到匹配项。但是,当插入 value1 时,我希望它是原始的大写/小写字符。简而言之,我想在 column3 中使用 dF3aW 而不是 DF3AW。是否有捷径可寻? powershell 是否支持像 python 那样的传递赋值?
  • 请重新阅读我的回答。查找已经不区分大小写。为此,您不需要大写或小写任何内容。您的问题不是由于区分大小写的查找,而是因为您使用了错误的 CSV 列作为哈希表中的键。
【解决方案2】:

为避免必须将字符串转换为小写,只需使用-icontains 比较运算符(“i”表示不区分大小写的比较):

所以不是

If ($hashTable.ContainsKey($_.csv2ColumnTwo)){

试试这个:

If ($hashTable.keys -icontains $_.csv2ColumnTwo){

【讨论】:

  • 由于某种原因,它仍在打印 else 语句 :(
【解决方案3】:

你能把它们全部变成小写吗?

$a = ipcsv 'C:\path\test1.csv'
$a | % {$_.csv1columntwo = $_.csv1columntwo.tolower()}
$a

$b = ipcsv 'C:\path\test2.csv'
$b | % {$_.csv2ColumnOne = $_.csv2ColumnOne.tolower(); $_.csv2ColumnTwo = $_.csv2ColumnTwo.tolower()}
$b

【讨论】:

  • 让我试一试。实际上我不能把它们写得更低,它们必须不被篡改,但如果我能把它们读得更低,那就行了......
  • 由于某种原因,这对我不起作用,我将在上面给出答案,这似乎更容易且更改较少......不过谢谢。
【解决方案4】:

Ansgar 基本上有正确的答案,但有一个错误。它正在将第二个文件中的行打印为qwer,,,而它应该打印qwer,,No value found from csv file2。在第一个 if 语句中还有一个条件需要添加,如下所示。

$list = Import-Csv 'C:\path\test1.csv' | Select-Object -Expand csv1ColumnTwo

Import-Csv 'C:\path\test2.csv' |
  Select-Object -Property *, @{n='csv1ColumnThree';e={
    if (($list -contains $_.csv2ColumnTwo) -and ($_.csv2ColumnTwo)) {
      $_.csv2ColumnTwo
    } elseif (-not ($_.csv2ColumnTwo)) {
      'No value found from csv file2'
    } else {
      'No value found from csv file1'
    }
}} | Export-Csv 'C:\path\testresults.csv' -NoType

第二个文件中的空值被检查为真,因此永远不会到达 elseif。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 2011-06-11
    • 1970-01-01
    • 2013-04-04
    相关资源
    最近更新 更多