Home > Net >  Increment "position" property by 1 for each matching property?
Increment "position" property by 1 for each matching property?

Time:07-30

This is a bit of a tough problem to explain, so I'll do my best.

I have two arrays, Categories and Items, and I'm attempting to build a third array called CategoryItems based off of those first two arrays. The function I currently have to build it looks like this:

const newCategoryItems = data.map(( item, i ) => {
  const category = categoriesData.find(c => c.name === item.category_name);

  return {
    item_id: bulkInsertData[i].id,
    category_id: category?.id,
    position: ???
  };
});
console.log({ newCategoryItems });

Each Category can have multiple Items. What I would like to do is assign that specific Item's position within that Category. So for example, if Category 1 contains five Items, then their positions would increment from 1-5, and once Category 2 is detected then the next Items would start their position at 1, and so on.

Is this possible within my current function?

Edit Here is some sample data:

raw data

const data = [
  {
    name: 'Item 1',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1,
    category_name: 'Category 1',
    qty: null
  },
  ... other raw data
]

I am then inserting those into my database and receiving these back with their assigned IDs. categories:

const categoriesData = [
  {
    id: 148,
    name: 'Category 1',
    list_id: 2,
    updated_at: '2022-07-28T18:00:23.09351 00:00',
    created_at: '2022-07-28T18:00:23.09351 00:00',
  },
  {
    id: 149,
    name: 'Category 2',
    list_id: 2,
    updated_at: '2022-07-28T18:00:23.09351 00:00',
    created_at: '2022-07-28T18:00:23.09351 00:00',
  },
  ... other categories
]

items:

const bulkInsertData = [
  {
    id: 677,
    name: 'Item 1',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
  },
  {
    id: 678,
    name: 'Item 2',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
  },
  {
    id: 679,
    name: 'Item 3',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
  },
  ...other items
]

CodePudding user response:

This would work. I've edited the test data by adding category directly to the first array to make this easier/more clear to reproduce. You could probably make an even more terse version using array.reduce().

const items = [
  {
    id: 677,
    name: 'Item 1',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1,
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
    category: 'test1'
  },
  {
    id: 678,
    name: 'Item 2',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1,
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
    category: 'test2'
  },
  {
    id: 679,
    name: 'Item 3',
    price: 0,
    quantity: 1,
    url: null,
    user_id: 1,
    created_at: '2022-07-28T18:00:22.810136 00:00',
    updated_at: '2022-07-28T18:00:22.810136 00:00',
    category: 'test1'
  }
];

const categoryCounter = {};
const newCategoryItems = items.map(( item ) => {

  if ( categoryCounter.hasOwnProperty( item.category ) ) {
    categoryCounter[item.category]  ;
  } else {
    categoryCounter[item.category] = 1;
  }
    
    
  return {
    item_id: item.id,
    category_id: item.category,
    position: categoryCounter[item.category]
  };
});

console.log( newCategoryItems );
https://stackoverflow.com/questions/73170086/increment-position-property-by-1-for-each-matching-property#

CodePudding user response:

Using object to store positions:

const categories = {}
function position(item, category) {
    if (!(category in categories)) categories[category] = {}

    if (!(item in categories[category])) categories[category][item] = categories[category][item] = Object.keys(categories[category]).length   1

    return categories[category][item]
}            

position("item 1", "category 1")
1
position("item 1", "category 1")
1
position("item 2", "category 1")
2
position("item 3", "category 2")
1
position("item 4", "category 1")
3
categories
{category 1: {…}, category 2: {…}}
category 1: {item 1: 1, item 2: 2, item 4: 3}
category 2: {item 3: 1}

Using array to store positions:

const categories = {}
function position(item, category) {
    if (!(category in categories)) categories[category] = []

    if (!(item in categories[category])) categories[category].push(item)

    return categories[category].indexOf(item)
}            

position("item 1", "category 1")
0
position("item 2", "category 1")
1
position("item 3", "category 2")
0
position("item 4", "category 1")
2
categories
{category 1: Array(3), category 2: Array(1)}
category 1: (3) ['item 1', 'item 2', 'item 4']
category 2: ['item 3']
[[Prototype]]: Object
  • Related