3

I have the following object array:

var list = [{
  "id": 119,
  "files": []
}, {
  "id": 126,
  "files": [{
    "id": 9,
    "filename": "test1.docx",
  }, {
    "id": 10,
    "filename": "test2.docx",
  }]
}]

How can update the list by deleting the file with a specific id (file ids are unique) So for example I want to delete the file with id of 10 .

This is what I've tried so far using underscore but it doesnt work:

_.each(list.item, function(item, idx) {
  if (_.findWhere(item.files, { id: 10 })) {
    //remove file from files array
    files.splice(idx, 1); 
  }
});

I want to update the list by deleting file object with a particular id

All the solutions so far create a copy of the original. Is there any way to simply splice it out from the original list?

2
  • @RoryMcCrossan typo sorry Commented Nov 29, 2017 at 16:23
  • Please explain If I have both the item id and file id then how can I delete the file object?, do you mean to delete the files with the supplied id and file id independently or files with a given item id? Commented Nov 29, 2017 at 16:50

5 Answers 5

1

You can in fact do it completely without underscore:

var list = [{"id": 119, "files": []}, {"id": 126, "files": [{"id": 9, "filename": "test1.docx"}, {"id": 10, "filename": "test2.docx", }]}]

var itemId = 126
var fileId = 10

var out = list.map(function(item) {
    if (item.id === itemId) {
        // Copy the item in order to not mutate the original object
        var itemCopy = Object.assign({}, item)
        itemCopy.files = itemCopy.files.filter(function(file) { return file.id !== fileId })
        return itemCopy
    } else return item
})

console.log(out)
    

Sign up to request clarification or add additional context in comments.

1 Comment

I want the original list updated. also how can i achieve if i only have the file id?
0

You can do it with native javascript this way:

1) How can I delete a file object if I only have the file id? (file ids are unique)

// ES6 version
const deleteFile1Es6 = (fileId) => {
    for(item of list){
        const file = item.files.filter(file => file.id === fileId)[0];
        if(file != null){
            item.files.splice(item.files.indexOf(file), 1);
            break;
        }
    }
};

// ES5 version
function deleteFile1Es5(fileId) {
    for(var i = 0; i < list.length; i++){
        var item = list[i];
        var fileFoundIndex = -1;
        for(var j = 0; j < item.files.length; j++){
            var file = item.files[j];
            if(file.id === fileId){
                fileFoundIndex = j;
                break;
            }
        }
        if(fileFoundIndex !== -1){
            item.files.splice(fileFoundIndex, 1);
            break;
        }
    }
}

2) If I have both the item id and file id then how can I delete the file object?

const deleteFile2Es6 = (itemId, fileId) => {
    const item = list.filter(item => item.id === itemId)[0];
    if(item != null){
        const file = item.files.filter(file => file.id === fileId)[0];
        if(file != null){
            item.files.splice(item.files.indexOf(file), 1);
        }
    }
};

1 Comment

what would be the equivalent of your first example in ES5?
0

you can do it by combining _without with findWhere. I'm guessing you want to delete whole array of that id.

var list = [
               {
                 "id": 119,
                 "files": []
                },
                {
                 "id": 126,
                 "files": [
                     {
                       "id": 9,
                       "filename": "test1.docx",
                     },
                     {
                       "id": 10,
                       "filename": "test2.docx",
                     }
                   ]
                }
             ];
list = _.without(list, _.findWhere(list, {
  id: 119
}));
console.log(list);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

3 Comments

Better to create a repl.it than using a code snippet because the latter won't run due to _ being undefined
I added _ and made the code run, yet it does not appear to be able to change the nested array. If I change id: 3 to id: 119 it remove from that layer, but when it comes to remove from the second layer (e.g.id: 10) it does not work.
@samnu no only the file object with that id should be removed
0

As an aside: you can also do this in ES6 using the new object spread operator and filtering out those objects that don't match the id. Of course, this returns a new object rather than deleting objects from the existing one, but it might be an option for you.

const out = list.map(el => {
  return {
    ...el,
    files: el.files.filter(f => f.id !== 9)
  }
});

DEMO

This wasn't previously possible without a Babel plugin, but it looks like it's landed in modern browsers now.

Comments

0

You can use array#forEach to iterate through your list array and then use array#filter to get all files which don't have the file id and re-assign to files array for each job.

var list = [{ "id": 119, "files": [] }, { "id": 126, "files": [{ "id": 9, "filename": "test1.docx", }, { "id": 10, "filename": "test2.docx", }] }];
var deleteWithFileId = (fileId) => list.forEach((o) => {
  o.files = o.files.filter(({id}) => fileId !== id);
});
deleteWithFileId(10)
console.log(list);

ES 5 Code

var list = [{ "id": 119, "files": [] }, { "id": 126, "files": [{ "id": 9, "filename": "test1.docx" }, { "id": 10, "filename": "test2.docx" }] }];
var deleteWithFileId = function (fileId) {
  return list.forEach(function (o) {
    o.files = o.files.filter(function (obj) {
      return fileId !== obj.id;
    });
  });
};
deleteWithFileId(10);
console.log(list);

To remove files and item id, you can first filter on item id and from this you can filter on the files.

var list = [{ "id": 119, "files": [] }, { "id": 126, "files": [{ "id": 9, "filename": "test1.docx", }, { "id": 10, "filename": "test2.docx", }] }];
var deleteWithItemAndFileId = (itemId, fileId) => {
  list.forEach(o => {
    if (o.id === itemId) {
      o.files = o.files.filter(({id}) => id !== fileId);
    }
  })
}

deleteWithItemAndFileId(126, 10)
console.log(list);

8 Comments

if I have both the item id and file id how can I achieve the same. So if i have a huge list it would just need to check the the one item if it contains the matching file id and if it does then remove the file. Prefreably in ES5
You can first filter on item id and then filter on file id. This will do the trick for you. Do you want to remove the files id from the matched items ?
yes i need to remove the matching file. file ids are unique in entire object array. but if I know the item id then no need to check entire list of items and then also each items file array to remove the one file. I need an updated object array and not a copy. Your foreach will unecessary loop through an entire list.
I have added another solution to first remove the items and then removes the files based on the id you supplied.
that solution deletes the item as well. We dont want to delete the item only the file
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.