Построить массив объектов из некоторых массивов - PullRequest
0 голосов
/ 31 января 2019

У меня есть следующие массивы:

const countries = ['Belgium', 'Uk']
const years = ['2019', '2018', '2017']
const colors = ['red', 'orange', 'green']

Мне нужен такой массив:

const result = [
  {
    country: 'Belgium',
    year: '2019',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Belgium',
    year: '2018',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Belgium',
    year: '2017',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Uk',
    year: '2019',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Uk',
    year: '2018',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Uk',
    year: '2017',
    red: random(min, max),
    orange: random(min, max),
    green: random(min, max),
  },
  {
    country: 'Tot',
    year: '2019',
    red: // sum of the values of the red key for each country in the year 2019,
    orange: // sum of the values of the orange key for each country in the year 2019,
    green: // sum of the values of the green key for each country in the year 2019,
  },
  {
    country: 'Tot',
    year: '2018',
    red: // sum of the values of the red key for each country in the year 2018,
    orange: // sum of the values of the orange key for each country in the year 2018,
    green: // sum of the values of the green key for each country in the year 2018,
  },
  {
    country: 'Tot',
    year: '2017',
    red: // sum of the values of the red key for each country in the year 2017,
    orange: // sum of the values of the orange key for each country in the year 2017,
    green: // sum of the values of the green key for each country in the year 2017,
  },
]

Итак, для каждого года и для каждой страны должен существовать объектсодержащий ключи каждого цвета.Значение должно быть случайным.

Тогда должны быть другие объекты с country = Total и со значениями цветов, набирающими сумму значений других объектов.

Это то, что я пытаюсьделать:

function createValues() {
  const min = 0
  const max = 300
  const dataset: any = []
  countries.forEach(country => {years.forEach(year => {colors.forEach(color => {dataset.push({country: country, year: year, [color]: random(min, max),})})})})}

Но это не работает, и я не знаю, как вычислить значения суммы.

Ответы [ 7 ]

0 голосов
/ 31 января 2019

Оператор двойного уменьшения и распространения.

Для каждой страны, а затем для каждого года мы создаем новый JSON.Этот json состоит из ключа страны + года и цветов, которые мы должны циклировать.Затем мы добавляем итог.

function random(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

const countries = ['Belgium', 'Uk'];
const years = ['2019', '2018', '2017'];
const colors = ['red', 'orange', 'green'];

const arr = countries.reduce((tmp, x) => [
  ...tmp,

  ...years.map(y => colors.reduce((json, z) => {
    json[z] = random(0, 255);

    return json;
  }, {
    country: x,
    year: y,
  })),
], []);

// add the Tot
const arrWithTotal = [
  ...arr,
  
  ...years.map(y => colors.reduce((json, x) => {
    json[x] = arr.reduce((tmp, z) => z.year === y ? tmp + z[x] : tmp, 0);

    return json;
  }, {
    country: 'Tot',
    year: y,
  })),
];

console.log(arrWithTotal);
0 голосов
/ 31 января 2019
const countries = ['Belgium', 'Uk']
const years = ['2019', '2018', '2017']
const colors = ['red', 'orange', 'green']
countries.push('Total');
result = [];
function random(min, max) {
   return Math.floor(Math.random() * (max - min)) + min;
}
countries.forEach(item => {
if (item !== 'Total') {
    yearArr = [];
    years.forEach(y => {
        obj = {
            country: item,
             year: y
        }
        colors.forEach(c => {
            obj[c] = random(0, 300)
        })
        result.push(obj)
        yearArr.push(obj)
    })
    }
})
years.forEach(y => {
    obj = result.filter(({ year, country }) => (year === y && country 
        !== 'total'))
    .reduce((a, b) => ({ country: 'total', year: a.year, red: a.red + 
      b.red, orange: a.orange + b.orange, green: a.green + b.green }))
     result.push(obj)
})
console.log(result);
0 голосов
/ 31 января 2019

Вот чисто функциональное решение.Он использует локальную мутацию в Array#reduce, но само вычисление чисто:

const ap = fs => xs => xs.flatMap (x => fs.map (f => f (x)))
const lift2 = f => xs => ys => ap (xs.map (f)) (ys)

// source: https://stackoverflow.com/a/1527820/411632
const random = min => max => {
    const min_ = Math.ceil (min)
    const max_ = Math.floor (max)
    
    return Math.floor (Math.random () * (max - min + 1)) + min
}

//////////////////////////////////////////////////////////////

const countries = ['Belgium', 'Uk']
const years = ['2019', '2018', '2017']


const output1 = lift2 (year => country => ({
     country,
     year,
     red: random (1) (255),
     orange: random (1) (255),
     green: random (1) (255)  
})) (years) (countries)

const output2 = Object.values (
   output1.reduce ((o, { year, red, green, orange, ...rest }) => {
      const { 
        red:red_ = 0, 
        green:green_ = 0, 
        orange:orange_ = 0 
      } = o[year] || {}
   
      o[year] = { 
          ...rest,
          country: 'Tot',
          year, 
          red: red + red_, 
          green: green + green_, 
          orange: orange + orange_
      }
   
      return o
    }, {})
)

const output3 = [...output1, ...output2]

console.log (output3)
0 голосов
/ 31 января 2019

Вы можете сделать что-то подобное, используя forEach и reduce

  • Получите все возможные комбинации стран и лет в combo
  • reduce комбои получить сумму для каждого цвета, сгруппированного на основе года
  • concat массива combo и общих значений, сгруппированных из reduce

const countries = ['Belgium', 'Uk']
const years = ['2019', '2018', '2017']
const colors = ['red', 'orange', 'green']

function random(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

const combo = [];

countries.forEach(country => {
  years.forEach(year => {
  
    const obj = {country,year};
    colors.forEach(color => {
      obj[color] = random(1, 10)
    })

    combo.push(obj)
  })
})

const total = combo.reduce((acc, {year, country,...rest}) => {
  acc[year] = acc[year] || {year,country: 'Tot'};

  for (let color in rest) {
    acc[year][color] = (acc[year][color] + rest[color]) || rest[color]
  }

  return acc;
}, {})


const final = combo.concat(Object.values(total))

console.log(final)
0 голосов
/ 31 января 2019

Мое решение

const countries = ['Belgium', 'Uk'];
const years = ['2019', '2018', '2017'];
const colors = ['red', 'orange', 'green'];

const min = 0;
const max = 300;

console.log(getTotal(
  getResult(countries, years, colors),
  colors
  ));

function getResult(countries, years, colors) {
  const result = [];
  countries.forEach(country => {
    years.forEach(year => {
      const item = {
        country: country,
        year: year
      };
      colors.forEach(color => {
        item[color] = random(min, max);
      });
      result.push(item);
    });
  });
  return result;
}

function getTotal(data, colors) {
  const total = {};
  data.forEach(item => {
    if (typeof total[item.year] === 'undefined') {
      total[item.year] = {};
      colors.forEach(color => {
        total[item.year][color] = item[color];
      });
    } else {
      colors.forEach(color => {
        total[item.year][color] += item[color];
      });
    }
  });
  for (var totalItem in total) {
    data.push({country: 'Tot', year: totalItem, ...total[totalItem]});
  }
  return data;
}

function random(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
}
0 голосов
/ 31 января 2019

Вы можете получить декартовы результаты по странам и годам, получить все итоги и построить недостающие итоговые объекты.

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) ? v : [v]).forEach(w =>
                (w && typeof w === 'object' ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

function random(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
}

const
    countries = ['Belgium', 'Uk'],
    years = ['2019', '2018', '2017'],
    colors = ['red', 'orange', 'green'],
    result = getCartesian({ country: countries, year: years })
        .map(o => Object.assign(o, ...colors.map(k => ({ [k]: random(0, 300) })))),
    totals = result.reduce((r, o) => (colors.forEach(color => {
        r[o.year] = r[o.year] || {};
        r[o.year][color] = (r[o.year][color] || 0) + o[color];
    }), r), {});

result.push(...years.map(year => Object.assign(
    { country: 'TOT', year },
    ...colors.map(color => ({ [color]: totals[year][color] }))
)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 31 января 2019

Вот как это работает:

const countries = ['Belgium', 'Uk']
const years = ['2019', '2018', '2017']
const colors = ['red', 'orange', 'green']
const dataset = [];


countries.forEach((country)=>{
  years.forEach((year)=>{
    const obj = {
      country: country,
      year: year 
    }
    colors.forEach((color)=>{
        obj[color] = Math.floor(Math.random() * 300) + 1;
      })
    dataset.push(obj);
  })
})

console.log(dataset);

https://jsfiddle.net/martinmakesitwork/0x1may62/9/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...