更改我的数组的结构

时间:2018-06-11 19:58:35

标签: javascript arrays object

我想改变结果的结构。有对象“itemGroup”,我想删除它们并保持键“水果”和“蔬菜”。

[{"id": 1, "shop": "shop1", "itemGroup": {"fruit": 2, "vegetable": 2},"total":4},
    {"id": 2, "shop": "shop2", "itemGroup": {"fruit": 0, "vegetable": 1},"total":1}]

我想要这个结果

[ 
{ "id": 1, "shop": "shop1", "fruit": 2, "vegetable": 2, "total": 4 }, 
{ "id": 2, "shop": "shop2" "fruit": 0, "vegetable": 1, "total": 1 } 
]

我的代码

var myArray = [
{shop: "shop1",item1: "my apple 1",item2: "my carrot 1"},
{shop: "shop1",item1: "my apple 1",item2: "my carrot 1"},
{shop: "shop2",item1: "my apple 0",item2: "my carrot 0"},
{shop: "shop2",item1: "my apple 0",item2: "my carrot 1"}
];

var MyArrayDefinition = [
{item: "my apple 0",color: "red", group: "fruit",score: 0},
{item: "my carrot 1",color: "orange",group: "vegetable",score: 1},
{item: "my apple 1",color: "red", group: "fruit",score: 1},
{item: "my carrot 0",color: "orange",group: "vegetable",score: 0}
];

var k = Object.keys,
items = MyArrayDefinition.reduce((o, v) => (o[v.item] = v, o), {});

var shops = myArray.reduce((o, v, i, s) => (
                s = v[k(v).find(k => k)],
                s = o[s] || (o[s] = {
                    fruit: 0,
                    vegetable: 0,
                            }),
                k(v).forEach(k => k.includes('item') &&
                    (s[(i = items[v[k]]).group] += i.score)), o), {});

            var result = k(shops).map((k, i) => ({
                id: i + 1,
                shop: k,
                itemGroup: shops[k],
                total:Object.values(shops[k]).reduce((a, b) => a + b),
            }));

4 个答案:

答案 0 :(得分:3)

与过去几天的大部分问题非常相似。 :-)

您可以映射数据,使用Object.assign并删除itemGroup。

let x = f.map(e => {
  e = Object.assign(e, e.itemGroup);
  delete e.itemGroup;
  return e;
})

console.log(x);
<script>
let f = [{
    "id": 1,
    "shop": "shop1",
    "itemGroup": {
      "fruit": 2,
      "vegetable": 2
    },
    "total": 4
  },
  {
    "id": 2,
    "shop": "shop2",
    "itemGroup": {
      "fruit": 0,
      "vegetable": 1
    },
    "total": 1
  }
]
</script>

答案 1 :(得分:0)

使用map是将数据从一个数组转换到另一个数组并在需要时运行计算的方法。

// Create a function that takes in your result array
function setPercentage (array) {

  // Helper function that calculates percentage
  function percentage (amount, total) {
    return (amount / total) * 100
  }

  // Map the results of the input array onto a new array,
  // and return the result
  return array.map((obj) => {
    return {
      id: obj.id,
      shop: obj.shop,
      fruit: percentage(obj.itemGroup.fruit, obj.total),
      vegetable: percentage(obj.itemGroup.vegetable, obj.total),
      total: obj.total
    }
  })

}

// pass in the result array from your code...
const shops_by_percentage = setPercentage(result)


console.log(shops_by_percentage)

/** result in the console.log()
 *
   [
     {
       'id': 1,
       'shop': 'shop1',
       'fruit': 50,
       'vegetable': 50,
       'total': 4
     },
     {
       'id': 2,
       'shop': 'shop2',
       'fruit': 0,
       'vegetable': 100,
       'total': 1
     }
   ] 
 *
 * */

答案 2 :(得分:0)

您可以在下面找到问题的一般解决方案。

使用此方法,您可以在项目数组中创建无限数量的项目,并在定义中创建无限数量的组,您的代码仍将按预期工作。最后,你的分数值作为权重(当你给出一些项目例如得分2时,每次出现将被视为两个项目。)

&#13;
&#13;
// Your items
const items = [
  {
    shop: "shop1",
    item1: "my apple 1",
    item2: "my carrot 1",
  },
  {
    shop: "shop1",
    item1: "my apple 1",
    item2: "my carrot 1"
  },
  {
    shop: "shop2",
    item1: "my apple 0",
    item2: "my carrot 0"
  },
  {
    shop: "shop2",
    item1: "my apple 0",
    item2: "my carrot 1"
  },
];

// Your definitions
const definitions = [
  {
    item: "my apple 0",
    color: "red",
    group: "fruit",
    score: 0
  },
  {
    item: "my carrot 1",
    color: "orange",
    group: "vegetable",
    score: 1
  },
  {
    item: "my apple 1",
    color: "red",
    group: "fruit",
    score: 1
  },
  {
    item: "my carrot 0",
    color: "orange",
    group: "vegetable",
    score: 0
  }
];

function groupShops(items) {
  return items.reduce((acc, cur) => {
    // Find shop with id of current item in accumulator
    const currentShop = acc.find(shop => shop.id === cur.shop);
    
    // Get all shop items
    const shopItems = Object.keys(cur)
      // Filter shop key as it is shop's ID
      .filter(key => key !== 'shop')
      // Map keys into values
      .map(key => cur[key]);
    
    // If shop already exists in accumulator
    if (!!currentShop) {
      // Return updated accumulator
      return acc
        // Remove current shop
        .filter(shop => shop !== currentShop)
        // And add new copy of current shop with new items to the accumulator
        .concat({
          id: currentShop.id,
          items: currentShop.items.concat(shopItems),
        });
    }
    
    // If shop doesn't exist in accumulator add it there and return updated accumulator
    return acc.concat({
      id: cur.shop,
      items: shopItems,
    });
  }, []);
};

function extendItems(shops) {
  // Filter items which have score 0 or less
  const filterItems = items => items.filter(item => item.score > 0);
  
  // Map though shops
  return shops.map(shop => {
    // Return updated shop
    return {
      // Keep shop id
      id: shop.id,
      // Extend itemIds by the properties stored in the definition and filter them
      items: filterItems(shop.items.map(item => definitions.find(definition => definition.item === item))),
    }
  });
}

function calculateResult(shop, index) {
  // Get all available groups
  const availableGroups = definitions.reduce((acc, cur) => acc.indexOf(cur.group) > -1 ? acc : acc.concat(cur.group), []);
  
  // Calculate total possible score
  const getTotalScore = () => shop.items.reduce((acc, cur) => cur.score + acc, 0);
  
  // Get score of a passed group
  const getGroupScore = group => shop.items.reduce((acc, cur) => cur.group === group ? acc + cur.score : acc, 0);
  
  // Loop though each available group and get its score
  const resultData = availableGroups.reduce((acc, cur) => {
    return {
      // Copy data from accumulator
      ...acc,
      // Add new property to the accumulator with a property key {group name} and value {percantage}
      [cur]: getGroupScore(cur, shop.items) / getTotalScore(shop.items) * 100,
    }
  }, {});
  
  // Return result object
  return {
    // Destruct items of the result object 
    ...resultData,
    // Store total items count
    total: shop.items.length,
    // Store shop id
    shop: shop.id,
    // Store index
    id: index,
  }
}

// Groups shops
const groupedShops = groupShops(items);

// Groups shops with extended items
const extendedShops = extendItems(groupedShops);

// You result object
const result = extendedShops.map((shop, index) => calculateResult(shop, ++index));

console.log(result);
&#13;
&#13;
&#13;

答案 3 :(得分:0)

阐述您的原始问题&#34;设置商店中每件商品的百分比,并回答您修改后的问题&#34;更改我的数组的结构,这可以通过修改原始代码来实现。

let myArray = [{"shop":"shop1","item1":"my apple 1","item2":"my carrot 1"},{"shop":"shop1","item1":"my apple 1","item2":"my carrot 1"},{"shop":"shop2","item1":"my apple 0","item2":"my carrot 0"},{"shop":"shop2","item1":"my apple 0","item2":"my carrot 1"}]
let MyArrayDefinition = [{"item":"my apple 0","color":"red","group":"fruit","score":0},{"item":"my carrot 1","color":"orange","group":"vegetable","score": null},{"item":"my apple 1","color":"red","group":"fruit","score":1},{"item":"my carrot 0","color":"orange","group":"vegetable","score":0}]

let k = Object.keys
let items = MyArrayDefinition.reduce((o, v) => (o[v.item] = v, o), {})

let shops = myArray.reduce(function (o, v, i, s) {
  return s = v[k(v).find(function (k) {
    return k;
  })], s = o[s] || (o[s] = {
    fruit: 0,
    vegetable: 0
  }), k(v).forEach(function (k) {
    return k.includes('item') && (s[(i = items[v[k]]).group] += i.score);
  }), o;
}, {});

// Helper function that calculates percentage
function percentage (amount, total) {
  if (total === 0) { // added check for 0 divisor
    return `0%`
  }
  return `${(amount / total) * 100}%`
}

let result = k(shops).map((k, i) => {
  let total = Object.values(shops[k]).reduce((a, b) => a + b) | 0 // added check if number else 0
  let fruit = shops[k].fruit | 0 // added check if number else 0
  let veg = shops[k].vegetable | 0 // added check if number else 0
  return {
    id: i + 1,
    shop: k,
    fruit: fruit,
    vegetable: veg,
    total: total,
    fruitPercentage: percentage(fruit, total),
    vegetablePercentage: percentage(veg, total)
  }
})

console.log(JSON.stringify(result, null, 2))
/** result from console.log()
 *
   [
     {
       "id": 1,
       "shop": "shop1",
       "fruit": 2,
       "vegetable": 2,
       "total": 4,
       "fruitPercentage": "50%",
       "vegetablePercentage": "50%"
     },
     {
       "id": 2,
       "shop": "shop2",
       "fruit": 2,
       "vegetable": 0,
       "total": 2,
       "fruitPercentage": "100%",
       "vegetablePercentage": "0%"
     }
   ]
 * */