merging array itself in javascript - javascript

My array looks like this:
{"type":"send","name":"kebab","quantity":"1"},
{"type":"send","name":"potato","quantity":"25000"},
{"type":"receive","name":"money","quantity":"1"},
{"type":"receive","name":"soul","quantity":"12"},
{"type":"receive","name":"paper","quantity":"8"},
{"type":"send","name":"kebab","quantity":"1"},
{"type":"send","name":"potato","quantity":"25000"},
{"type":"receive","name":"money","quantity":"1"},
{"type":"receive","name":"soul","quantity":"12"},
{"type":"receive","name":"paper","quantity":"8"}
I want it to merge into new array where the values would be added or subtracted, like this:
{"type":"send","name":"kebab","quantity":"2"},
{"type":"send","name":"potato","quantity":"50000"},
{"type":"receive","name":"money","quantity":"2"},
{"type":"receive","name":"soul","quantity":"24"},
{"type":"receive","name":"paper","quantity":"16"}
I can't figure it out how to do that
update: type and name should stay the same, only quantity would be changed

You can reduce the items down to a new array and add up the quantities.
const items = [{"type":"send","name":"kebab","quantity":"1"},
{"type":"send","name":"potato","quantity":"25000"},
{"type":"receive","name":"money","quantity":"1"},
{"type":"receive","name":"soul","quantity":"12"},
{"type":"receive","name":"paper","quantity":"8"},
{"type":"send","name":"kebab","quantity":"1"},
{"type":"send","name":"potato","quantity":"25000"},
{"type":"receive","name":"money","quantity":"1"},
{"type":"receive","name":"soul","quantity":"12"},
{"type":"receive","name":"paper","quantity":"8"}]
let result = items.reduce((arr, item) => {
// Find the item in the new array by name
let found = arr.find(i => i.name == item.name && i.type == item.type)
// If the item doesn't exist add it to the array
if(!found) return arr.concat(item)
// If the item does exist add the two quantities together
// This will modify the value in place, so we don't need to re-add it
found.quantity = parseFloat(item.quantity) + parseFloat(found.quantity)
// Return the new state of the array
return arr;
}, [])
console.log(result)

You can use reduce to group the array into an object. Use Object.values to convert the object into an array.
var arr = [{"type":"send","name":"kebab","quantity":"1"},{"type":"send","name":"potato","quantity":"25000"},{"type":"receive","name":"money","quantity":"1"},{"type":"receive","name":"soul","quantity":"12"},{"type":"receive","name":"paper","quantity":"8"},{"type":"send","name":"kebab","quantity":"1"},{"type":"send","name":"potato","quantity":"25000"},{"type":"receive","name":"money","quantity":"1"},{"type":"receive","name":"soul","quantity":"12"},{"type":"receive","name":"paper","quantity":"8"}];
var result = Object.values(arr.reduce((c, v) => {
c[v.name] = c[v.name] || {type: "",name: v.name,quantity: 0};
c[v.name].quantity += +v.quantity; //Update the quantity
c[v.name].type = v.type; //Update the type
return c;
}, {}));
console.log(result);

Related

Sort an array of objects based on frequency but keep repeated elements

I have an array of objects,
const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];
myArray.sort((a, b) => a.k_id - b.k_id);
console.log(myArray);
I want it to be sorted based on the k_id and it occurrences(descending frequency). But, have to keep all the elements as I have other values in the objects. Other key, value pairs can be in any order. (I have simplified my issue here with only two key, value pairs but the actual array have more than 15 key, value pairs)
Output Produced:
(8) [{id:1,k_id:1},{id:3,k_id:1},{id:2,k_id:2},{id:6,k_id:2},{id:7,k_id:2},{id:4,k_id:3},{id:5,k_id:3},{id:8,k_id:4}]
Expected output, because I need them to be sorted like below as k_id:2 occured more than k_id:1:
myArray = [{id:6, k_id:2},{id:7, k_id:2},{id:2, k_id:2},{id:3, k_id:1},{id:1, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:8, k_id:4}];
Looking for something like this?
inp.sort((a, b) =>
inp.filter(c => c.k_id === b.k_id).length -
inp.filter(c => c.k_id === a.k_id).length
);
// sorting a vs b by counting the occurency of each k_id property value
// using filter
const inp = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];
console.log(
inp.sort((a, b) => inp.filter(c => c.k_id === b.k_id).length - inp.filter(c => c.k_id === a.k_id).length)
)
try this out, I'm not sure if it would scale but, it works fine.
const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];
(()=>{
const keys = {}
const newArray = [];
/**
* Determenin every keys count
*/
for(const one of myArray){
// if the key is not yet registered in keys
// initialize 0 and add one either way
// on the key count
keys[one.k_id] = (keys[one.k_id] || 0) + 1;
}
console.log(keys)
//
function GetTheHighestFrequency () {
/**
* #return {object} highest
*
* containing a key or K_id
* and its frequency count
*/
let highest = { key:0,frequency:0 };
for(const [key,value] of Object.entries(keys)){
if(value > highest.frequency)
highest = { key,frequency:value };
}
return highest
}
//
// return new array
for(const each of Object.keys(keys)){
// request the highest frequency key K_id
const highest = GetTheHighestFrequency();
//
// Add (Push) objects in the newArray
//
for(const one of myArray){
// add an object if
// if the K_id matches the current
// highest key value
if(String(one.k_id) === highest.key)
newArray.push(one)
}
delete keys[highest.key]
}
console.log("the result is = ",newArray)
})()
I would suggest first creating a frequency lookup. Below I've used reduce with a Map, but you can use a regular object and a for loop to build the same look up. The Map has keys which are the k_id, and the value of each k_id is the number of times k_id occurs. Creating the lookup means you don't need to loop through your array each iteration of your sort. You can then use .sort() and sort by the occurrences for each key_id stored within the frequency map. As this uses .sort(), the sort is stable, so items with the same k_id will keep their relative ordering from the original array:
const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];
const freq = myArray.reduce((acc, {k_id}) => acc.set(k_id, (acc.get(k_id) || 0) + 1), new Map);
myArray.sort((a, b) => freq.get(b.k_id) - freq.get(a.k_id));
console.log(myArray);

Sort array elements on JavaScript

I have an array, each subarray of which contains different positions in different order:
[
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
]
I need to sort it on JavaScript (ES6) and i expect to get an array like this:
[
["apple(2)", "banana(5)", "peach(0)"],
["apple(0)", "banana(1)", "peach(3)"],
["apple(1)", "banana(0)", "peach(0)"]
]
Order of each subarray should be the same. If subarray don't have some position, i need to add it with 0 value. Can i using something like map() or sort() function or need to compare it manually?
Here is functional programming approach, using a Map and reduce:
const data = [['apple(2)', 'banana(5)'],['peach(3)', 'banana(1)'],['apple(1)'],];
// Create a Map with default values for each name, i.e. with "(0)":
let names = new Map(data.flat().map(item => [item.replace(/\d+/, ""), item.replace(/\d+/, "0")]));
let result = data.map(row =>
[...row.reduce((map, item) =>
map.set(item.replace(/\d+/, ""), item), // Overwrite default
new Map(names) // Start with clone of original Map
).values()]
);
console.log(result);
You have to loop over to get the keys used. You then have to loop over a second time to get the fill in the missing keys. There are many ways of doing it, this is one.
var data = [
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
];
// match string and number
var re = /([^(]+)\((\d+)\)/;
// Loop over and find all of the keys
var grouped = data.reduce((info, subset, index) => {
subset.forEach(item => {
// find the key and count
var parts = item.match(re);
// have we seen this key?
if (!info[parts[1]]) {
// if not create an array
info[parts[1]] = Array(data.length).fill(0);
}
// set the key index with the count
info[parts[1]][index] = parts[2];
})
return info;
}, {});
// loop over the groups and fill in the set
Object.entries(grouped).forEach(([key, counts], colIndex) => {
counts
.forEach((cnt, rowIndex) => {
data[rowIndex][colIndex] = `${key}(${cnt})`;
})
});
console.log(data);
First get the unique words. Then traverse array of arrays to check if the word is present or not. If it is not present then make the word according to your condition and if present then put the original word to the tmp array. At last sort it for each iteration. By the way, I used regex replace method to get the word.
const data = [
['apple(2)', 'banana(5)'],
['peach(3)', 'banana(1)'],
['apple(1)'],
];
const words = [...new Set(data.flat().map((x) => x.replace(/[^a-z]/gi, '')))];
const ret = data.map((x) => {
const tmp = [];
const newX = x.map((y) => y.replace(/[^a-z]/gi, ''));
for (let i = 0, l = words.length; i < l; i += 1) {
if (newX.includes(words[i])) tmp.push(x.shift());
else tmp.push(`${words[i]}(0)`);
}
return tmp.sort();
});
console.log(ret);

To remove duplicate among array of objects corresponding to the other key and value pair of object using javascript

Have an array of objects with object having two key and value pairs.
[{fruit:"apple",locale:"US"},
{fruit:"orange",locale:"US"},
{fruit:"banana",locale:"US"},
{fruit:"apple",locale:"US"},
{fruit:"orange",locale:"IT"},
{fruit:"apple",locale:"IT"},
{fruit:"banana",locale:"IT"},
{fruit:"orange",locale:"IT"}
{fruit:"apple",locale:"IT"}]
How to achieve
Fruit should not be duplicate within same locale,
Fruit can be same with different locales.
You can filter out the objects by matching the index value of current iteration. Something like this:
var data=[{fruit:"apple",locale:"US"},{fruit:"orange",locale:"US"},{fruit:"banana",locale:"US"},{fruit:"apple",locale:"US"},{fruit:"orange",locale:"IT"},{fruit:"apple",locale:"IT"},{fruit:"banana",locale:"IT"},{fruit:"orange",locale:"IT"},{fruit:"apple",locale:"IT"}];
var result = data.filter((e,i,self)=>self.findIndex(k=>k.fruit==e.fruit && k.locale==e.locale)==i);
console.log(result);
Or you can make use of Map:
var data=[{fruit:"apple",locale:"US"},{fruit:"orange",locale:"US"},{fruit:"banana",locale:"US"},{fruit:"apple",locale:"US"},{fruit:"orange",locale:"IT"},{fruit:"apple",locale:"IT"},{fruit:"banana",locale:"IT"},{fruit:"orange",locale:"IT"},{fruit:"apple",locale:"IT"}];
var result = [...new Map(data.map(k=>[`${k.fruit}|${k.locale}`, k])).values()];
console.log(result);
Try this..
obj = [{fruit:"apple",locale:"US"},
{fruit:"orange",locale:"US"},
{fruit:"banana",locale:"US"},
{fruit:"apple",locale:"US"},
{fruit:"orange",locale:"IT"},
{fruit:"apple",locale:"IT"},
{fruit:"banana",locale:"IT"},
{fruit:"orange",locale:"IT"}
{fruit:"apple",locale:"IT"}]
const uniqueArray = this.obj.filter((item, index) => {
const temp = JSON.stringify(item);
return index === this.obj.findIndex(obj => {
return JSON.stringify(obj) === temp;
});
});
console.log(uniqueArray);

while pushing the data in to arrays, not added in order

enter image description here
i need to push the data one after another, but here i am getting to add in disorder like last added array in to first.
for (var key in data[tabName + scoreBreakDown]) {
var values = data[tabName + scoreBreakDown][key];
var staticData = values[0];
var obj = [];
obj.push(staticData.CompanyName);
obj.push(staticData.Country_ORIG);
for (var value in values) {
if (addHeader) {
headersArray.push(values[value].AspectName);
weightArray.push(values[value].ScoreWeight);
}
obj.push(values[value].SPESGScore_ORIG);
}
addHeader = false;
dataArray.push(obj);
}
You can use array.map to map through an array and transform it into a new array in order.
In this example, we are just multiplying each value by 3, but the transformation is arbitrary.
let loop = (arr) => {
return arr.map(item => {
return item*3
})
}
console.log(loop([1,2,3,4,5]))
If you want to loop through an object in order this way, you can use Object.keys() this will return an array of the keys in the object.
let loop = (obj) => {
return Object.keys(obj).map(item => {
return `${item}: ${obj[item]}`
})
}
let obj = {
first_name:"John",
last_name:"Doe",
age:23
}
console.log(loop(obj))
So instead of using a for loop and an if statement to check a condition and push the data to the array after each iteration, you can use something Array.filter() to remove entries you don't want to push, and return them in order.
data = [
{header:true, value:"item1"},
{header:false, value:"item2"},
{header:true, value:"item3"},
]
let array = data.filter(item => {return item.header}).map(item => {
return item.value
})
console.log(array)

Remove duplicate index value from first array, manipulate second as per first(at some specific conditions)

This is the tricky one :
please understand my scenario:
I have two array , both array will have equal length always.
I want remove duplicate value in first array and second array will be manipulated according first one.
like if i have array like :
var firstArr = [1,1,4,1,4,5]
var secArr = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi']
//I want below Output
//[1,4,5] // this is firstArr after manipulation
//['sagar|vilas|ganesh','suraj|more',abhi] // this is secArr after manipulation
// here all duplicate values will be removed from first array
// and at same index second array will be manipulated.
please check my fiddle:
https://jsfiddle.net/abhilash503001/du4fe8ob/86/
You can use Map and reduce
First loop through the first array and map it values as key and take the values from second array's respective index as key
Now you have loop on the map's entries take the key's will be your unique firstArr and to get desired value for second arr you need to join values by |
var firstArray = [1,1,4,1,4,5]
var secArr = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi']
let op = firstArray.reduce((op,inp,index) => {
if(op.has(inp)){
let val = op.get(inp)
val.push(secArr[index])
op.set(inp, val)
} else {
op.set(inp,[secArr[index]])
}
return op
},new Map())
let {firstArr, secondArr} = [...op.entries()].reduce((op,[first,second])=>{
op.firstArr.push(first)
op.secondArr.push(second.join('|'))
return op
},{firstArr:[],secondArr:[]})
console.log(firstArr)
console.log(secondArr)
This is how I did it.
You first group the texts into arrays and then join them together.
var index_array = [1,1,4,1,4,5]
var text_array = ['sagar', 'vilas', 'suraj', 'ganesh','more','abhi'];
var manipulated_text_array = [];
var manipulated_index_array = [];
var groups = {};
for (let index in index_array) {
if (groups[index_array[index]] == undefined) {
groups[index_array[index]] = [];
}
groups[index_array[index]].push(text_array[index]);
}
for (let index in groups) {
manipulated_text_array.push(groups[index].join("|"));
}
manipulated_index_array = Object.keys(groups).map(x => parseInt(x));
console.log("texts", manipulated_text_array);
console.log("indexes", manipulated_index_array);

Categories

Resources