JS:如果所有嵌套值都等于null,则删除对象键

Posted

技术标签:

【中文标题】JS:如果所有嵌套值都等于null,则删除对象键【英文标题】:JS: Delete Object Key if all nested Values equal null 【发布时间】:2019-09-07 00:37:46 【问题描述】:

从给定的数据结构(json 文件)中,我基本上需要渲染一个表格。不应呈现空行和/或列。我对 javascript 相当陌生,并尝试了不同的方法(转换为数组并使用 .map()、reduce()、.filter()、lodash 等)但没有成功。我什至不知道解决问题的最佳方法是什么。 (或者可能的搜索词是什么。)

“行键”(例如:mo、tu、we、th、fr)和“列键”(john、hane、doe)都不是已知的并且可以变化。

完整示例:https://jsbin.com/rafeyasena/edit?js,output

"groupA": 
    "mo":  "john": 8, "jane": 5, "doe": null ,
    "tu":  "john": 8, "jane": 5, "doe": null ,
    "we":  "john": 5, "jane": 9, "doe": null ,
    "th":  "john": 6, "jane": 3, "doe": null ,
    "fr":  "john": null, "jane": null, "doe": null 
  

可能产生的数据结构

const header = ["John", "Jane"];
const content = [
 "mo": [ 8, 5 ],
 "tu": [ 8, 5 ],
 "we": [ 5, 9 ],
 "th": [ 6, 3 ]
]

预期结果(前端,React):

   | John | Jane |
---|------|--------
mo |  8   |  5   |
tu |  8   |  5   |
we |  5   |  9   |
th |  6   |  3   |

到目前为止我尝试了什么: 我能够删除 null 的所有值和相应的键,如果它不再包含键/值 (Delete null values in nested javascript objects) - 让我面临找出所有剩余键来构建表头的挑战。 (在下面的示例中,这将只有 John 和 Jane - 所以基本上是一种遍历所有键并记录至少存在一次的每个键的方法)。所以我目前的数据看起来是这样的(但我不确定这是否是最好的方法):

"groupA": 
    "mo":  "john": 8, "jane": 5, ,
    "tu":  "john": 8, "jane": 5, ,
    "we":  "john": 5, "jane": 9, ,
    "th":  "john": 6, "jane": 3, 
  

【问题讨论】:

【参考方案1】:

我只是将数据表示为 2D 数组(这使得渲染更容易):

 const columnNames = [""];
 const rows = [columnNames];

  for(const [rowName, values] of Object.entries(groupA)) 
     const row = [rowName];
     for(const [columnName, value] of Object.entries(values)) 
        let position = columnNames.indexOf(columnName);
        if(value === null) continue;
        if(position === -1)
          position = columnNames.push(columnName) - 1;
        row[position] = value;
     
     rows.push(row);
 

 // just some debugging:   
 console.log( rows.map(row => row.map(it => (it || "").padStart(10)).join("|")).join("\n") );

【讨论】:

谢谢!你的答案比我能写的所有内容都要紧凑。第一次弄清楚数组解构。我试着理解“let position = columnNames.indexOf(columnName)”部分。目前代码仍然输出空行(其中没有任何值) - 但这应该很容易修复。非常感谢您的努力!【参考方案2】:

我认为创建后一种格式(删除空值)是非常有用的第一步。从那里你可以写这样的东西来把它变成你的目标格式的变体:

const uniqKeys = (obj) => [... new Set(Object.values(obj).flatMap(Object.keys))]

const transform = (group, headers = uniqKeys(group)) => (
  headers,
  content: Object.entries(group).reduce(
    (a, [k, v]) => (...a, [k]: headers.map(h => v[h])),
    
  )
)


const groupA = mo: john: 8, jane: 5, tu: john: 8, jane: 5, we: john: 5, jane: 9, th: john: 6, jane: 3

console.log(transform(groupA))

请注意,目标与您的请求略有不同,因为您的示例内容不是合法的 JS([ 8, 5 ] 没有意义),但我认为它抓住了它的精神,返回如下内容:


  headers: ['john', 'jane'],
  content: 
    mo: [8, 5],
    tu: [8, 5],
    we: [5, 9],
    th: [6, 3]
  

请注意,此功能比要求更通用,因为您可以为其提供标题列表并仅从数据中提取这些标题。

【讨论】:

【参考方案3】:

看看object-scan。一旦你了解它是如何工作的,它就会使这种事情变得相对容易。以下是您回答问题的方式

// const objectScan = require('object-scan');

const isNullObject = (obj) => (
  obj instanceof Object
  && !Array.isArray(obj)
  && Object.values(obj).every((e) => e === null)
);

const prune = (data) => objectScan(['**'], 
  rtn: 'count',
  filterFn: ( value, parent, property ) => 
    if (isNullObject(value)) 
      delete parent[property];
      return true;
    
    return false;
  
)(data);

const stats =  groupA:  mo:  john: 8, jane: 5, doe: null , tu:  john: 8, jane: 5, doe: null , we:  john: 5, jane: 9, doe: null , th:  john: 6, jane: 3, doe: null , fr:  john: null, jane: null, doe: null   ;

console.log(prune(stats)); // return number of replaces
// => 1

console.log(stats);
/* =>
   groupA:
     mo:  john: 8, jane: 5, doe: null ,
      tu:  john: 8, jane: 5, doe: null ,
      we:  john: 5, jane: 9, doe: null ,
      th:  john: 6, jane: 3, doe: null   
*/
.as-console-wrapper max-height: 100% !important; top: 0
<script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是object-scan的作者

【讨论】:

以上是关于JS:如果所有嵌套值都等于null,则删除对象键的主要内容,如果未能解决你的问题,请参考以下文章

如果为 null,则 JsonPatchDocument 实例化嵌套对象

JS:从嵌套数组中删除对象并返回父数组

PHP数组中,如何查询所有等于指定值得元素下标?

如果所有汇总值都是NA,则dplyr汇总保留NA

js的if语句判断条件到底是啥情况

如果numpy数组的所有元素都等于某个值,则从numpy数组中删除行/列