fix compact to handle empty list or record in column (#15213)

If a table contains an empty list or record in one column and both column
and -e flags are used, then skip that row.

`compact -e` now skips empty values in a column where as before they were
ignored. Example:

 ```nu
[["a", "b"]; ["c", "d"], ["h", []]] 
| compact -e b
```
before

```plain
 #   a         b
────────────────────────
 0   c   d
 1   h   [list 0 items]
```
after
```plain
 #   a   b
───────────
 0   c   d
```
This commit is contained in:
hardfault 2025-03-01 12:47:55 +00:00 committed by GitHub
parent 7555743ccc
commit e9b677a9e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 4 deletions

View File

@ -108,10 +108,15 @@ pub fn compact(
return false;
}
if compact_empties {
if let Value::String { val, .. } = x {
if val.is_empty() {
return false;
}
// check if the value is one of the empty value
if match x {
Value::String { val, .. } => val.is_empty(),
Value::Record { val, .. } => val.is_empty(),
Value::List { vals, .. } => vals.is_empty(),
_ => false,
} {
// one of the empty value found so skip now
return false;
}
}
}

View File

@ -37,3 +37,58 @@ fn discards_empty_rows_by_default() {
assert_eq!(actual.out, "4");
}
#[test]
fn discard_empty_list_in_table() {
let actual = nu!(pipeline(
r#"
[["a", "b"]; ["c", "d"], ["h", []]] | compact -e b | length
"#
));
assert_eq!(actual.out, "1");
}
#[test]
fn discard_empty_record_in_table() {
let actual = nu!(pipeline(
r#"
[["a", "b"]; ["c", "d"], ["h", {}]] | compact -e b | length
"#
));
assert_eq!(actual.out, "1");
}
#[test]
fn dont_discard_empty_record_in_table_if_column_not_set() {
let actual = nu!(pipeline(
r#"
[["a", "b"]; ["c", "d"], ["h", {}]] | compact -e | length
"#
));
assert_eq!(actual.out, "2");
}
#[test]
fn dont_discard_empty_list_in_table_if_column_not_set() {
let actual = nu!(pipeline(
r#"
[["a", "b"]; ["c", "d"], ["h", []]] | compact -e | length
"#
));
assert_eq!(actual.out, "2");
}
#[test]
fn dont_discard_null_in_table_if_column_not_set() {
let actual = nu!(pipeline(
r#"
[["a", "b"]; ["c", "d"], ["h", null]] | compact -e | length
"#
));
assert_eq!(actual.out, "2");
}