英文:
Find objects that start with the same value and keep only the longest value in the array Powershell
问题
我正在尝试找到一个筛选我的数组的解决方案。
对于筛选条件,它将是:如果第3列的一个对象与该列的另一个对象匹配(或包含)。然后删除它。
以下是$data的示例:
By Mode File
-- ---- ----
user1 Read creation. ABC
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read edition\File
user2 Read edition\File\DATA SHEETS
user2 Read BCD
user2 Read BCD\DATA
user3 Read BCD
我想要删除具有相同开头的对象,只保留具有最多字符的对象。但是,如果不是同一用户,不应筛选该行。
我希望作为结果得到:
By Mode File
-- ---- ----
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read edition\File\DATA SHEETS
user2 Read BCD\DATA
user3 Read BCD
我尝试过:
foreach($elem in $data.file)
{
$data.file.Where({$_.contains($elem)}, 'First',3)
}
我被卡住了,感谢您的建议。
英文:
I am trying to find a solution to filter my array.
For the criterion it would be: if an object of the 3rd column matches (or contains) with another object of this same column. Then delete it.
Here is an example of $data:
By Mode File
-- ---- ----
user1 Read creation. ABC
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read edition\File
user2 Read edition\File\DATA SHEETS
user2 Read BCD
user2 Read BCD\DATA
user3 Read BCD
I want to delete the objects which have an identical beginning by keeping only the one which has the most characters.
However, if it is not the same user, the line should not be filtered.
what I am looking for as a result :
By Mode File
-- ---- ----
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read edition\File\DATA SHEETS
user2 Read BCD\DATA
user3 Read BCD
What I tried :
foreach($elem in $data.file)
{
$data.file.Where({$_.contains($elem)}, 'First',3)
}
I am stuck, thank you for your comments
答案1
得分: 4
以下是您要求的翻译内容:
<!-- language-all: sh -->
在得到有用的评论后,我认为这就是您要找的内容,假设我们有示例输入存储在名为CSV的变量中:
```powershell
$csv = ConvertFrom-Csv @'
By,Mode,File
user1,Read,creation. ABC
user1,Read,creation. ABC\Invoice
user1,Read,creation. ABC\LIMITED
user2,Read,edition\File
user2,Read,edition\File\DATA SHEETS
user2,Read,BCD
user2,Read,BCD\DATA
user3,Read,BCD
'@
我们可以使用Group-Object
、Sort-Object
和String.StartsWith
的组合:
# 使用 `By` 属性对对象进行分组并枚举它们
$csv | Group-Object By | ForEach-Object {
# 对组按 `File` 属性进行排序(升序)
$sorted = @($_.Group | Sort-Object File)
# 并枚举每个组
for($i = 0; $i -lt $sorted.Count; $i++) {
# 存储当前项
$current = $sorted[$i]
# 以及此集合中的下一项
$next = $sorted[$i + 1]
# 如果此组中有下一项,并且下一项的 `File` 属性以与当前项相同的字符串开头
# 例如:`'edition\File\DATA SHEETS'.StartsWith('edition\File')`
if($next -and $next.File.StartsWith($current.File, [StringComparison]::InvariantCultureIgnoreCase)) {
# 我们可以假定这个可以跳过
continue
}
# 否则,输出它
$current
}
}
这个示例产生的输出将是:
By Mode File
-- ---- ----
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read BCD\DATA
user2 Read edition\File\DATA SHEETS
user3 Read BCD
请注意,我已经将代码部分保留在原文中,只翻译了相关的注释和文本。
<details>
<summary>英文:</summary>
<!-- language-all: sh -->
Following the helpful comments, I believe this is what you're looking for, assuming we have the example input stored in a variable called CSV:
$csv = ConvertFrom-Csv @'
By,Mode,File
user1,Read,creation\1. ABC
user1,Read,creation\1. ABC\Invoice
user1,Read,creation\1. ABC\LIMITED
user2,Read,edition\File
user2,Read,edition\File\DATA SHEETS
user2,Read,BCD
user2,Read,BCD\DATA
user3,Read,BCD
'@
We can use a combination of [`Group-Object`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/group-object?view=powershell-7.3), [`Sort-Object`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/sort-object?view=powershell-7.3) and [`String.StartsWith`](https://learn.microsoft.com/en-us/dotnet/api/system.string.startswith?view=net-8.0):
group the objects by the By
property and enumerate them
$csv | Group-Object By | ForEach-Object {
# sort the groups by the File
property (ascending)
$sorted = @($_.Group | Sort-Object File)
# and enumerate each group
for($i = 0; $i -lt $sorted.Count; $i++) {
# store the current item
$current = $sorted[$i]
# and the next item in this collection
$next = $sorted[$i + 1]
# if there is a next item in this group AND
# the next item File
property starts with the same string as the current item
# i.e.: 'edition\File\DATA SHEETS'.StartsWith('edition\File')
if($next -and $next.File.StartsWith($current.File, [StringComparison]::InvariantCultureIgnoreCase)) {
# we can assume this one can be skipped
continue
}
# else, output it
$current
}
}
The produced output from this example would be:
```none
By Mode File
-- ---- ----
user1 Read creation. ABC\Invoice
user1 Read creation. ABC\LIMITED
user2 Read BCD\DATA
user2 Read edition\File\DATA SHEETS
user3 Read BCD
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论