【问题标题】:Lodash - Remove one property for every element in array without specify indexLodash - 为数组中的每个元素删除一个属性而不指定索引
【发布时间】:2022-01-25 07:12:52
【问题描述】:

我正在构建一个允许我比较两个对象的组件。它接受要比较的字段列表和需要忽略的字段列表字符串格式

这里是一个将被比较的对象的例子:

{

// (..... More elements above .....)

taskData: {
    "uniqueId": "OrdenTrabajo48",
    "id": 48,
    "position": 1,
    "name": "Dirección Obra Civil",
    "description": "Dirección Obra Civil Afecta: Sorda, Roberto",
    "startDate": "2021-10-16T11:00:00.000Z",
    "endDate": "2022-06-01T11:00:00.000Z",
    "duration": 227,
    "progress": 73,
    "hours": 0,
    "realHours": 15,
    "predecessor": null,
    "child": [],
    "resourceInfo": [
        {
            "uniqueId": "Persona_1MJ0VE9G0",
            "id": "OrdenTrabajo48Persona_1MJ0VE9G0",
            "name": "Sorda, Roberto",
            "group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
            "unit": 4.1667,
            "startDate": "2021-10-16T03:00:00.000+00:00",
            "endDate": "2022-06-01T02:59:59.000+00:00",
            "hours": 0,
            "realHours": 15,
            "avatar": "http://localhost:8091/images/llama.jpg"
        }
    ],
    "comments": null,
    "etiquetas": [],
    "baseLineStartDate": null,
    "baseLineEndDate": null
}

// (..... More elements below .....)

}

(但澄清一下,它可以是任何对象。组件是抽象的,可以在任何地方使用)

组件不知道要比较的对象的结构,只知道对象和字符串格式的路径

我想删除数组的每个元素resourceInfo,属性avatar、icon、label和color不管数组的长度如何,但我不知道是否有这样做的语法。

我也想删除属性realHours

这是我尝试过的:


const ignoredFields = [
'taskData.resourceInfo[?].avatar',    //<--- It's not working
'taskData.resourceInfo[].icon',      //<---  Neither this
'taskData.resourceInfo.label',     //<--- Or this
'taskData.resourceInfo[0].color',     //<--- This hardcode is working, but I don't know the length in that scope
'taskData.realHours' // <-- No problems here

];

const currentComparableObject = _.omit(obj, ignoredFields);
const oldComparableObject = _.omit(prev, ignoredFields);

【问题讨论】:

  • 我将添加另一个步骤并使用路径 taskData.resourceInfo 并迭代该数组并在每个对象上省略数组字段 ['avatar','icon','label'] 等
  • 对,我怎么能把它抽象化?比较两个对象的组件并不真正知道需要比较的对象的详细信息。它只知道一个对象和需要忽略的属性的名称
  • 然后,如果您不知道结构,则需要递归跟踪路径并同时遍历两个对象。我现在有点困惑,因为你似乎知道你想要什么路径
  • 我知道我想要比较和忽略的路径(父组件提供这些),但我不知道抽象组件中模型的结构

标签: javascript lodash


【解决方案1】:
var fieldsToOmit=[];
var resourceInfoFields=['avatar','icon','label','color'];
var globalFields=['realHours'];
taskData.resourceInfo.forEach((item,index)=>{
  resourceInfoFields.forEach((field)=>{
    fieldsToOmit.push(`resourceInfo[${index}].${field}`)
  })
})
console.log( _.omit(taskData, fieldsToOmit.concat(globalFields)))

【讨论】:

  • 聪明的方法
【解决方案2】:

您不需要 lodash 从数组中删除字段。我的意思是,如果你真的愿意,你可以这样做,但是循环遍历数组并删除你想要的字段是微不足道的。

@Yasser CHENIK 没有错,只是没有很好地解释解决方案。

下面我提供了一个完整的示例,以便您自己测试。

注意这个解决方案改变了原始数组,但是使用这个概念来制作一个不可变的版本并不难。

const taskData = {
    "uniqueId": "OrdenTrabajo48",
    "id": 48,
    "position": 1,
    "name": "Dirección Obra Civil",
    "description": "Dirección Obra Civil Afecta: Sorda, Roberto",
    "startDate": "2021-10-16T11:00:00.000Z",
    "endDate": "2022-06-01T11:00:00.000Z",
    "duration": 227,
    "progress": 73,
    "hours": 0,
    "realHours": 15,
    "predecessor": null,
    "child": [],
    "resourceInfo": [
        {
            "uniqueId": "Persona_1MJ0VE9G0",
            "id": "OrdenTrabajo48Persona_1MJ0VE9G0",
            "name": "Sorda, Roberto",
            "group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
            "unit": 4.1667,
            "startDate": "2021-10-16T03:00:00.000+00:00",
            "endDate": "2022-06-01T02:59:59.000+00:00",
            "hours": 0,
            "realHours": 15,
            "avatar": "http://localhost:8091/images/llama.jpg"
        },
        {
            "uniqueId": "Persona_1MJ0VE9G0",
            "id": "OrdenTrabajo48Persona_1MJ0VE9G0",
            "name": "Sorda, Roberto",
            "group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
            "unit": 4.1667,
            "startDate": "2021-10-16T03:00:00.000+00:00",
            "endDate": "2022-06-01T02:59:59.000+00:00",
            "hours": 0,
            "realHours": 15,
            "avatar": "http://localhost:8091/images/llama.jpg"
        },
        {
            "uniqueId": "Persona_1MJ0VE9G0",
            "id": "OrdenTrabajo48Persona_1MJ0VE9G0",
            "name": "Sorda, Roberto",
            "group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
            "unit": 4.1667,
            "startDate": "2021-10-16T03:00:00.000+00:00",
            "endDate": "2022-06-01T02:59:59.000+00:00",
            "hours": 0,
            "realHours": 15,
            "avatar": "http://localhost:8091/images/llama.jpg"
        },
    ],
    "comments": null,
    "etiquetas": [],
    "baseLineStartDate": null,
    "baseLineEndDate": null
}


const fieldsToOmit = [
    'avatar',
    'icon',
    'label',
    'color',
    'realHours'
]

console.log(taskData.resourceInfo);

taskData.resourceInfo.forEach(info => {
    fieldsToOmit.forEach(field => {
        delete info[field];
    })
});

console.log(taskData.resourceInfo);

【讨论】:

  • 您好,感谢您的回答。问题是,比较对象的组件不知道对象的结构,只知道字符串格式的字段路径。 (即:taskData.realHours。) lodash 提供了一种通过字符串路径导航到对象的方法,但不提供以这种方式迭代数组的方法。
  • 很有趣。对于误解了请求,我深表歉意。祝你好运!
【解决方案3】:

您可以使用解构以函数方式(不可变)删除属性:

const {realHours, ...result} = {
    ...taskData, 
    resourceInfo: taskData.resourceInfo.map(
        ({avatar, icon, label, color, ...keep}) => keep
    )
};
console.log(result);

【讨论】:

  • 这个答案是艺术。
【解决方案4】:

感谢大家的回答。

为了部分解决问题,我创建了一个执行以下操作的函数:

  • 它过滤包含[?]的引用(即:taskData.resourceInfo[?].avatar)

  • 然后获取字符串的第一部分(即到达数组的路径)和第二部分(属性名)

  • 使用 lodash 中的 _.get 检索数组的长度并使用索引创建一个新的 fieldReference,因此 loadash 可以读取它。

private sanitizeArrays(obj: any, fieldReferences: string[]): string[] {
        const fieldsDup = [...fieldReferences];

        // Get Elements that contains [?] in the property name
        const arrays = fieldsDup.filter(ignoredField => ignoredField.match(/\[\?]/g));

        // Remove elements that contain [?] from ignoredFieldsDuplicated
        fieldsDup.forEach((ignoredField, index) => {
            if (ignoredField.includes('[?]')) {
                fieldsDup.splice(index, 1);
            }
        });

        // Get the properties names without [?]
        const arrayPropertyName = arrays.map(ignoredField => ignoredField.split('[')[0]);
        const afterArrayPropertyName = arrays.map(ignoredField => ignoredField.split(']')[1]);

        // For each array that I have...
        arrayPropertyName.forEach((array, index) => {
            const length = _.get(obj, array).length;

            for (let i = 0; i < length; i++) {

                fieldsDup.push(array + '[' + i + ']' + afterArrayPropertyName[index]);
            }
        });

        return fieldsDup;
    }

示例输入(如果对象在resourceInfo中只包含一个元素):

'taskData.resourceInfo[?].avatar',
                      'taskData.resourceInfo[?].icon',
                      'taskData.resourceInfo[?].label',
                      'taskData.resourceInfo[?].color',
                      'taskData.resourceInfo[?].fontColor',
                      'taskData.realHours'

示例输出:

taskData.resourceInfo[?].icon
taskData.resourceInfo[?].color
taskData.realHours
taskData.resourceInfo[0].avatar
taskData.resourceInfo[0].icon
taskData.resourceInfo[0].label
taskData.resourceInfo[0].color
taskData.resourceInfo[0].fontColor

(javascript includes() 删除 [?] 效果不好)

它也不适用于嵌套数组...

【讨论】:

    猜你喜欢
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 2016-03-18
    • 1970-01-01
    相关资源
    最近更新 更多