Home > Enterprise >  How to move object inside another object in the same array
How to move object inside another object in the same array

Time:11-18

I have 3 arguments in a move function those are list,source and destination. List is here :

const list = [
      {
        id: '1',
        name: 'Folder 1',
        files: [
          { id: '2', name: 'File 1' },
          { id: '3', name: 'File 2' },
          { id: '4', name: 'File 3' },
          { id: '5', name: 'File 4' },
        ],
      },
      {
        id: '6',
        name: 'Folder 2',
        files: [{ id: '7', name: 'File 5' }],
      },
    ];

in a given function I should enter the source and destination and I could move for example move(list, '4', '6') then I expect file with id 4 moved to the folder which has id 6.

Like that :

const result = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [
      { id: '7', name: 'File 5' },
      { id: '4', name: 'File 3' },
    ],
  },
];

I moved it Received: {"files": [{"id": "7", "name": "File 5"}, {"id": "4", "name": "File 3"}], "id": "6", "name": "Folder 2"} but I couldn't delete the value that id is 4.

Here is my code

let copyList =list.slice();

 const filteredVal =  copyList[0].files.find((file: { id: Object; })=> { 

  return file.id == source
 } );// 2-3-4-5

//  if (copyList[0].files.id === source){
//   delete copyList[0].files.source
//  } -> Doesn't work.


 copyList[1].files.push(filteredVal);

 return copyList[1]

I am using typescript also I'm testing it with jest I don't wait for the direct answers just I need steps to go or any need to write from scratch with another technique.

CodePudding user response:

This should work, I leave you some comments

function move(list, fileId, folderId) {
  // This does not copy the objects inside list, prefer something like JSON.parse(JSON.stringify(list)) to do a deep copy
  const copyList = list.slice();
  // Get the files from the folder where is located your fileId
  const { files: originFiles } = copyList.find(({ files }) => files.some(({ id }) => id === fileId))
  // Get the index of the file to move
  const fileToMoveIndex = originFiles.findIndex(({ id }) => id === fileId)
  // Find the destination folder with the folderId
  const destinationFolder = copyList.find(({ id }) => id === folderId)
  // Add the file in the destination folder
  destinationFolder.files.push(originFiles[fileToMoveIndex])
  // Remove the file from it origin folder
  originFiles.splice(fileToMoveIndex, 1)
  return destinationFolder
}
move(list, '4', '6');
console.log(list);
<script>
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];
</script>

CodePudding user response:

If you don't mind a mutating solution, here is one that is fairly easy to understand.

Loop through all files in every folder until you find the file that matches the provided sourceFileID. Then search the folder that matches the provided destinationFolderID. If both are found, remove the file from the source and add it to the destination.

function move(folders, sourceFileID, destinationFolderID) {
  // intentional `var` usage, these variables are accessible outside of the for-block
  for (var sourceFolder of folders) {
    var iFile = sourceFolder.files.findIndex(file => file.id == sourceFileID);
    if (iFile >= 0) break;
  }
  
  if (iFile < 0) return; // source file not found
  
  const destinationFolder = folders.find(folder => folder.id == destinationFolderID);
  
  if (!destinationFolder) return; // destination folder not found
  
  const [file] = sourceFolder.files.splice(iFile, 1);
  destinationFolder.files.push(file);
}

const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];

move(list, "4", "6");
console.log(list);
div.as-console-wrapper { max-height: 100% }

CodePudding user response:

Here is the long way around without testing if the id was found

NOTE how I copy the array - slice will not make a deep copy.

const move = (list, from, to) => {
  const arr = JSON.parse(JSON.stringify(list)); // safer than slice
  const fromFiles = arr.find(({files}) => files.some(({id}) =>  id === from))?.files; // array of source files
  if (!fromFiles || fromFiles.length === 0) return null;
  const fromFile = fromFiles.splice(fromFiles.findIndex(({id}) =>  id === from),1);  // remove and return source file
  const toFiles = arr.find(({id}) => id === to)?.files;
  if (!toFiles || toFiles.length === 0) return null;
  toFiles.push(fromFile); // push the file to the destination array.
  return arr
  
}
console.log("--- 1 ---\n"); 
console.log(move(list, '4', '6')); // new array
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
console.log("--- 2 ---\n"); 
console.log(move(list, '8', '6')); // from not found
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
console.log("--- 3 ---\n"); 
console.log(move(list, '7', '6')); // to not found
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
<script>
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];
</script>

CodePudding user response:

You can just delete the element with splice or filter

const move = (list, source, dest) => {
  let copyList = list.slice();
  const filteredVal = copyList[0].files.find((file) => file.id == source);
  // with filter
  copyList[0].files = copyList[0].files.filter((file) => file.id !== source)
  // or with splice
  // copyList[0].files.splice(copyList[0].files.findIndex((file)=> file.id == source), 1)
  copyList[1].files.push(filteredVal);
  return copyList
}
console.log(move(list, '4', '6'))

console.log(list)
<script>
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];
</script>

  • Related