Convert Array To a Specific Object - javascript

What is the best way to convert this array :
array=['a', 'b', 'c', 'd']
to
$scope.editcity = {
cities : [
{id: 1, name: "a", selected: false},
{id: 2, name: "b", selected: false},
{id: 3, name: "c", selected: false},
{id: 4, name: "d", selected: false}
]}

With a map
var array=['a', 'b', 'c', 'd']
var $scope = {} // just for this test - you wont need this line
$scope.editcity = {
cities : array.map(function(c,i){
return {
id: i+1,
name: c,
selected:false
}
})
};
console.log($scope.editcity)

Use Array#map method.
var array = ['a', 'b', 'c', 'd']
$scope.editcity = {
cities : array.map(function(v, i){
return {
id : i + 1,
name : v,
selected : false
}
})
}
var array = ['a', 'b', 'c', 'd']
var editcity = {
cities: array.map(function(v, i) {
return {
id: i + 1,
name: v,
selected: false
}
})
}
console.log(editcity);

You can use reduce method to return object.
var array=['a', 'b', 'c', 'd']
var editcity = array.reduce(function(r, e, i) {
r.city = (r.city || []).concat({id: i + 1, name: e, selected: false})
return r
}, {})
console.log(editcity)

Related

How to compare object based on key and value and remove from array

I have below data in const rows.
const rows = {
"selected_parameter_value": [
{
"parameter_value": "a",
"label_value": "a"
},
{
"parameter_value": "d",
"label_value": "d"
}
]
};
I want to compare each and every object of
const rows.selected_parameter_value with parameter_value
and label_value from this.selectedParameterContext.records[0].selected_parameter_value.
And delete those objects from this.selectedParameterContext.records[0].selected_parameter_value which are not present in const rows.selected_parameter_value
For example -
In the const rows.selected_parameter_value, only a and d object are present, b and c are not present.
So remove object whose parameter and label values are b and c from this.selectedParameterContext.records[0].selected_parameter_value.
this.selectedParameterContext = {
'records': [
{
'selected_parameter_value': [{
'parameter_value': 'a',
'label_value': 'a'
},
{
'parameter_value': 'b',
'label_value': 'b',
}]
},
{
'selected_parameter_value': [{
'parameter_value': 'c',
'label_value': 'c'
},
{
'parameter_value': 'd',
'label_value': 'd',
}]
}]
};
**Expected Output -**
this.selectedParameterContext = {
'records': [
{
'selected_parameter_value': [{
'parameter_value': 'a',
'label_value': 'a'
}]
},
{
'selected_parameter_value': [
{
'parameter_value': 'd',
'label_value': 'd',
}]
}]
};
I tried below code
deleteContextData(rows ) {
const paramArray = rows.selected_parameter_value;
const newArrayData = this.selectedParameterContext.records[0].selected_parameter_value;
const removeMatchingData = (paramArray, toCompareWith) => {
return paramArray.filter(({ label_value }) => !toCompareWith.some(compareObj => compareObj.label_value === label_value));
}
console.log(removeMatchingData(paramArray, newArrayData),"newarray");
}
You can filter the data/source using Array.filter by comparing each object by matching object with the same key-value present in the comparing/target array and return only the ones which are not matching in the source array.
let data = [{label_value: 'a', parameter_value: 'a'}, {label_value: 'b', parameter_value: 'b'}, {label_value: 'c', parameter_value: 'c'}, {label_value: 'd', parameter_value: 'd'}]
let contextData = [{label_value: 'b', parameter_value: 'b'}, {label_value: 'c', parameter_value: 'c'}];
const removeMatchingData = (data, toCompareWith) => {
return data.filter(({ label_value }) => !toCompareWith.some(compareObj => compareObj.label_value === label_value));
}
console.log(removeMatchingData(data, contextData));
contextData = [{label_value: 'b', parameter_value: 'b'}, {label_value: 'c', parameter_value: 'c'}, {label_value: 'e', parameter_value: 'e'}];
console.log(removeMatchingData(contextData, data));

Filtering an array with an array of values

I have 2 arrays and i'd like to filter one array with the other. E.g. if array1 includes any of the values in array2, they should be returned.
The two arrays are:
const array1 = [a, b, c, d]
The other array, which should be filtered where 'id' is equal to any of the values in array1 is:
const array2 = [
{
id: b
title: title1
},
{
id: d
title: title2
},
{
id: f
title: title3
}
]
The easiest way is to use two for-loops. Possible not the fastest approach.
res = [];
for (var i = 0;i<array1.length;i++) {
for (var j = 0;j<array2.length;j++) {
if (array1[i] == array2[j].id) {
res.push(array2[j]);
break;
}
}
}
You could use Array.prototype.filter() and Array.prototype.indexOf():
const array1 = ['a', 'b', 'c', 'd'];
const array2 = [{
id: 'b',
title: 'title1'
}, {
id: 'd',
title: 'title2'
}, {
id: 'f',
title: 'title3'
}];
const result = array2.filter(function(x){
return array1.indexOf(x.id) !== -1;
});
Adding this missing '', You can use filter and includes methods of Array.
const array1 = ['a', 'b', 'c', 'd'];
const array2 = [
{
id: 'b',
title: 'title1'
},
{
id: 'd',
title: 'title2'
},
{
id: 'f',
title: 'title3'
}
]
const result = array2.filter(({id}) => array1.includes(id));
console.log(result);

Javascript - Detect reverse pairs in an array of objects

I have an array of objects:
[
{source: 'A', target : 'C', value: 25},
{source: 'E', target: 'F', value: 5},
{source: 'C', target: 'A', value: 20}, ...
]
How can I detect all reverse pairs such as source: 'A', target: 'C' and source: 'C', target: 'A' and make a sum of value: 25 + 20 ?
First generate all possible pairs using two for loops, then iterate over each pari using forEach to check if the source/target properties match, if so, compute the sum:
const arr = [
{source: 'A', target : 'C', value: 25},
{source: 'E', target: 'F', value: 5},
{source: 'C', target: 'A', value: 20}
];
const pairs = arr => {
const out = [];
for (let i = 0; i < arr.length - 1; ++i) {
for (let j = i; j < arr.length - 1; ++j) {
out.push([arr[i], arr[j + 1]]);
}
}
return out;
}
pairs(arr).forEach(pair => {
if (pair[0].source === pair[1].target && pair[0].target === pair[1].source) {
console.log(pair[0].value + pair[1].value);
}
});
You could use a sorted joint key for a pair with a hash table.
var array = [{ source: 'A', target : 'C', value: 25 }, { source: 'E', target: 'F', value: 5}, { source: 'C', target: 'A', value: 20 }],
hash = {},
pairs = array.reduce((r, { source, target, value }) => {
var key = [source, target].sort().join('|');
if (!hash[key]) {
r.push(hash[key] = { source, target, value });
return r;
}
hash[key].value += value;
return r;
}, []);
console.log(pairs);
Try something like this
var abc = [
{source: 'A', target : 'C', value: 25},
{source: 'E', target: 'F', value: 5},
{source: 'C', target: 'A', value: 20},
{source: 'C', target: 'A', value: 200} //To test all pairs
]
//Here you can use for loop to get pairs of each record
var sourceA = abc[0].source;
var targetA = abc[0].target;
//check source against target and vice versa
var result = abc.filter(x => x.target == sourceA && x.source == targetA);
console.log("Result");
console.log(result);
//if you want sum then
var totalAmount = 0;
result.forEach( data => totalAmount = totalAmount + data.value);
console.log("Total amount");
console.log(totalAmount);
When you're looking for all the pairs, you can use:
var arr = [
{source: 'A', target : 'C', value: 25},
{source: 'E', target: 'F', value: 5},
{source: 'C', target: 'A', value: 20},
{source: 'D', target: 'A', value: 2},
{source: 'A', target: 'D', value: 1}
]
var res = arr.reduce((acc, {source,target,value}, id, input) => {
var findPair = el => el.source == target && el.target == source;
var pair = !acc.some(findPair) && input.find(findPair);
return pair ? [...acc, {source, target, sum: pair.value + value}]: acc;
}, []);
This returns:
[ { source: 'A', target: 'C', sum: 45 },
{ source: 'D', target: 'A', sum: 3 } ]

Sum children multiple values and save result to parent in n-ary tree in Javascript

I asked this: Sum children values and save result to parent in n-ary tree in Javascript
And I recieved an answer from #Nina Scholz. Now I am trying to use the same code but with more than one value, for instance:
value: {A: 1, B: 2, C: 3}
I tried something like this:
function update(array) {
var root = [],
references = array.reduce((r, o) => {
if (!o.parents.length) {
root.push(o.id);
}
r[o.id] = o;
return r;
},Object.create(null));
root.reduce(
function sum(s, id) {
var o = references[id];
for (var key in o.value) {
return s + (o.value[key] = o.children.reduce(sum, 0) || o.value[key])
}
}, 0);
return array;
}
var data2 = [{ id: 'A', parents: [], children: ['B', 'E'], value: {A:1, B:2} }, { id: 'B', parents: ['A'], children: ['C', 'D'], value: {A:1, B:2} }, { id: 'C', parents: ['B'], children: [], value: {A:1, B:2} }, { id: 'D', parents: ['B'], children: [], value: {A:1, B:2} }, { id: 'E', parents: ['A'], children: ['F'], value: {A:1, B:2} }, { id: 'F', parents: ['E'], children: [], value: {A:1, B:2} }]
console.log(update(data2));
But only works with the value A because of the return.
Another thing I tried:
function update(array) {
var root = [],
references = array.reduce((r, o) => {
if (!o.parents.length) {
root.push(o.id);
}
r[o.id] = o;
return r;
},Object.create(null));
root.reduce(
function sum(s, id) {
var o = references[id];
var x;
for (var key in o.value) {
x = (s + (o.value[key] = o.children.reduce(sum, 0) || o.value[key]));
}
}, 0);
return array;
}
var data2 = [{ id: 'A', parents: [], children: ['B', 'E'], value: {A:1, B:2} }, { id: 'B', parents: ['A'], children: ['C', 'D'], value: {A:1, B:2} }, { id: 'C', parents: ['B'], children: [], value: {A:1, B:2} }, { id: 'D', parents: ['B'], children: [], value: {A:1, B:2} }, { id: 'E', parents: ['A'], children: ['F'], value: {A:1, B:2} }, { id: 'F', parents: ['E'], children: [], value: {A:1, B:2} }]
console.log(update(data2));
But it does not work with the ones that have children.
You could adapt sum and iterate key/value for adding to the value object.
function update(array) {
function sum(s, id) {
var o = references[id];
o.value = o.children.reduce(sum, undefined) || o.value;
if (!s) {
return Object.assign({}, o.value);
}
Object
.entries(o.value)
.forEach(([k, v]) => s[k] = (s[k] || 0) + v);
return s;
}
var root = [],
references = array.reduce((r, o) => {
if (!o.parents.length) {
root.push(o.id);
}
r[o.id] = o;
return r;
}, Object.create(null));
root.reduce(sum, undefined);
return array;
}
var data2 = [{ id: 'A', parents: [], children: ['B', 'E'], value: { A: 1, B: 2 } }, { id: 'B', parents: ['A'], children: ['C', 'D'], value: { A: 1, B: 2 } }, { id: 'C', parents: ['B'], children: [], value: { A: 1, B: 2 } }, { id: 'D', parents: ['B'], children: [], value: { A: 1, B: 2 } }, { id: 'E', parents: ['A'], children: ['F'], value: { A: 1, B: 2 } }, { id: 'F', parents: ['E'], children: [], value: { A: 1, B: 2 } }]
console.log(update(data2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sort an array by its relative position

Example object array:
[{
id: 'a',
beforeId: null
}, {
id: 'b',
beforeId: 'c'
}, {
id: 'c',
beforeId: 'a'
}, {
id: 'd',
beforeId: 'b'
}]
Output order: d-b-c-a; each element sorted relative to each other element based on its beforeId property.
I could make a temporary array and sort the above array. Is sorting possible with array.sort?
You could build an object with the relations and generate the result by using the object with beforeId: null and unshift all objects for the result array.
The next object is the one with the actual val as key.
Complexity: O(2n).
function chain(array) {
var o = {}, pointer = null, result = [];
array.forEach(a => o[a.beforeId] = a);
while (o[pointer]) {
result.unshift(o[pointer]);
pointer = o[pointer].val;
}
return result;
}
var data = [{ val: 'a', beforeId: null }, { val: 'b', beforeId: 'c' }, { val: 'c', beforeId: 'a' }, { val: 'd', beforeId: 'b' }];
console.log(chain(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is a terribly inefficient and naïve algorithm, but it works:
const array = [
{id: 'a', beforeId: null},
{id: 'b', beforeId: 'c'},
{id: 'c', beforeId: 'a'},
{id: 'd', beforeId: 'b'}
];
// find the last element
const result = [array.find(i => i.beforeId === null)];
while (result.length < array.length) {
// find the element before the first element and prepend it
result.unshift(array.find(i => i.beforeId == result[0].id));
}
console.log(result);
Is sorting possible with array.sort?
sure, with a helper function:
graph = [
{id: 'a', beforeId: null},
{id: 'b', beforeId: 'c'},
{id: 'c', beforeId: 'a'},
{id: 'd', beforeId: 'b'}
];
let isBefore = (x, y) => {
for (let {id, beforeId} of graph) {
if (id === x)
return (beforeId === y) || isBefore(beforeId, y);
}
return false;
};
graph.sort((x, y) => x === y ? 0 : (isBefore(x.id, y.id) ? -1 : +1))
console.log(graph);
isBefore returns true if x is before y immediately or transitively.
For generic, non-linear topological sorting see https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
UPD: As seen here, this turned out to be horribly inefficient, because sort involves many unnecessary comparisons. Here's the fastest (so far) version:
function sort(array) {
let o = {}, res = [], len = array.length;
for (let i = 0; i < len; i++)
o[array[i].beforeId] = array[i];
for (let i = len - 1, p = null; i >= 0; i--) {
res[i] = o[p];
p = o[p].id;
}
return res;
}
which is the #Nina's idea, optimized for speed.
You may try this approach :
// order(null, vals, []) = ["d", "b", "c", "a"]
function order(beforeId, vals, result){
var id = beforeId || null;
var before = vals.filter(function(val){
return val.beforeId === id
});
if (before.length === 0) return result;
return order(before[0].val,
vals,
[before[0].val].concat(result));
}

Categories

Resources