I have an object which contains arrays. Here is an image of what it looks like in my browser:
I need to display, for example, only the first 2 arrays.
So far, I have tried this
var size = 2;
var sliced = joblist.slice(0, size);
However, this does not work and I get the following message
error:slice is not a function. it doesn't have a length
Can someone help me understand what I am doing wrong?
While the keys from the object have no order, you could take the keys, sort them and take the first two keys for a new object.
var joblist = {
'2017-08-08': [1],
'2017-08-09': [2],
'2017-08-10': [3, 4, 5],
'2017-08-11': [6]
},
size = 2,
topObjects = Object.assign(
...Object
.keys(joblist)
.sort()
.slice(0, size)
.map(k => ({ [k]: joblist[k] }))
);
console.log(topObjects);
Object does not have a .slice() method.
You can use Object.entries() to get an array of property, value pairs within the object then call .slice() on that array, chain .map() to set properties and values at a new object which can be passed to Object.assign() second parameter if an object is expected result
const o = {
a:[], b:[], c:[], d:[]
}
let res = Object.assign({}, ...Object.entries(o).slice(0, 2)
.map(([key, prop]) => ({[key]:prop})));
console.log(res)
var joblist = {
'obj': [1,2,3],
'obj2': [4,5,6],
'obj3': [7,8,9],
'obj4': [10,11,12],
};
var size = 2;
var i = 0;
for (var prop in joblist) {
if (i < size) {
console.log(joblist[prop]);
}
i++;
}
Object.keys(joblist).map(function(k) {
joblist[k] = joblist[k].slice(0, 2);
});
Related
function arraysCommon(array1, array2) {
return array1.filter(x => array2.includes(x));
}
This function does not work the way I want it to.
For instance given array1 = [1,2,3,2,1] and array2 = [5,4,3,2,1]
it returns [1,2,3,2,1], since the elements 1,2,3 are seen in both arrays.
But I want it to return [1,2,3] in that order since 1,2,3 are seen only once in array2 and are treated as seperate entities.
So pretty much the functionality should be that
Each element in the first array can map to at most one element in the second array.
Duplicated elements in each array are treated as separate entities.
the first array determines the order
I have attempted to loop through the arrays and check and compare the number of duplicates in each array but I can't seem to get the logic working correctly. Is there a different way to approach this?
I've attached an image of two Venn diagrams that might clarify the difference
Unfortunately, it gets more complicated because you need to know what numbers you have already added. In this case you need a temporary array to hold the result. We also need to track if a number exists in the array two times.
Try this:
function arraysCommon(array1, array2) {
//Copy array2 by duplicating and spreading the elements into another array.
var copyArray2 = [...array2];
//Temperary Array
var temp = [];
for (let x of array1) {
//Check if the element is in the first array and not already added to the temp array
if (copyArray2.includes(x)) {
temp.push(x);
//Remove item from copy array2 so it cannot be used anymore
copyArray2.splice(copyArray2.indexOf(x), 1);
}
}
//Return the temp array
return temp;
}
console.log(arraysCommon([1,2,3,2,1], [5,4,3,2,1]))
console.log(arraysCommon([1,2,3,2,1], [2,2,3,3,4]))
With sorting and counting this should be possible. Since you are incrementing when you find similar characters, this should be okay:
const array1= [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1]
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1,2]
const array5 = [1,2,3,2,1];
const array6 = [2,2,3,3,4]
function arraysCommon(array1, array2) {
const ans = [];
array1.sort();
array2.sort();
let j = 0;
let i = 0;
while(i<array1.length && j<array2.length){
if(array1[i] === array2[j]){
ans.push(array1[i]);
i++;
j++;
}
else if(array2[i] > array1[j]){
i++;
}
else{
j++;
}
}
console.log(ans);
}
arraysCommon(array1,array2);
arraysCommon(array3,array4);
arraysCommon(array5,array6);
this should work as you wanted!
// test 1
const array1 = [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1];
// test 2
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1];
const mapper = (array1, array2) => {
var obj = {};
array1.forEach((x, indexX) => {
array2.forEach((y, indexY) => {
if (x == y) {
if (!Object.values(obj).includes(indexX) && !obj.hasOwnProperty(indexY)) {
obj[indexY] = indexX;
return;
}
}
})
})
return Object.values(obj).sort().map(values => array1[values]);
}
console.log(mapper(array1, array2));
console.log(mapper(array3, array4));
I hope this helps. Cheers.
You can instance a new Set, wich brings only unique values and than retorn a array from this set.
Something like this:
function arraysCommon(array1, array2) {
const filtered = array1.filter(x => array2.includes(x));
const uniqueValues = new Set(filtered)
return Array.from(uniqueValues)
}
I have two arrays like:
arr1 = ["orange","banana"]
arr2 = [{"fruit"= ["pineapple","banana"]},{"fruit"= ["grapes","apple"]},{"fruit"= ["apple","orange"]}]
And i need to filter if in second array exists an item of the first.
I am trying to do this:
let kFilter = arr1.map(itemY => { return itemY; });
let filteredK = arr2.filter(itemX => kFilter.includes(itemX.fruit));
But no success :-(
First to avoid too much iteration convert the simple array to an object something like following. Otherwise the complexity will be high
const fruitMap = {
"orange": 1,
"banana": 1
};
Then you have to iterate over each of the items in second array
arr2.forEach(fruitsObj => {
let arr = fruitsObj['fruit'];
for (let i = 0; i < arr.length(); i ++) {
if (fruitMap[arr[i]]) {
arr.splice(i, 1);
}
}
})
//declaration variables correctly
let arr1 = ["orange","banana"]
let arr2 = [{"fruit" : ["pineapple","banana"]},{"fruit" : ["grapes","apple"]},{"fruit": ["apple","orange"]}];
//filter using reduce
arr2.filter((e)=>arr1.reduce((a,i)=>a||e["fruit"].includes(i),false))
//filter using some
arr2.filter((e)=>arr1.some((i)=>e["fruit"].includes(i)))
var arr = [1,2,3,4]
arr.map((x,i) => arr[i+1] - x)
// 1,1,1,NaN
Is there a way you can use the index in an Array.map or Array.filter method to compare value with-out comparing the final index to avoid the outcome of NaN?
You can use Array#slice to remove the last element before applying map.
var arr = [1,2,3,4]
console.log(arr.slice(0,-1).map((x,i) => arr[i+1] - x));
The shortest way you could do this would be
var mapped = arr.map((x,i) => arr[i+1] - x).filter(x => x);
Which is saying filter all the values where x is True
But I don't think you can do this with only map. I think map always returns an array of equal length.
You use reduce to achieve this though.
var arr = [1,2,3,4]
var reduced = arr.reduce((ids,x,i) => {
if (i < arr.length-1 ){
ids.push(arr[i+1] - x)
}
return ids
}, []);
console.log(reduced)
Outputs
[ 1, 1, 1 ]
Yes, you can. Just use Arra.filter() and return only the value that has a primitive value:
var arr = [1,2,3,4];
var newArr = arr.map((x,i) => arr[++i] - x)
.filter(val => val);
console.log(newArr);
I have one array that has objects whose keys match another array of objects with the same keys, and the value for the first key is a Month index (0 = January, 1 = February, etc.) and the points may cross a year division (a:10, a:11, a:0, a:1)
However the first array may not have the same number of objects, and the values for the key on one object may not exist in the other object on the same key, and vice-versa.
Assuming both arrays are already ordered correctly, I want to compare those two arrays, and if one array is missing an object with a value for a key that the other one has, I want to add a new object to the first array with the same key and value, in the same position/index within the array that doesn't have it, as it is in the array that does have it.
let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]
arr1 is missing objects with an a value of 10, 11, and 2 that exist in arr2, and arr2 is missing objects with an a value of 3 and 4 that exist in arr1
What I want to end up with is:
arr1 = [{a:10, b:0},{a:11, b:3},{a:0, b:1},{a:1, b:3},{a:2, b:0},{a:3, b:18},{a:4, b:2}]
arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1},{a:3, b:0},{a:4, b:0}]
Now arr1 has new items/objects for a:10, a:11, and a:2 while
arr2 has new items for a:3 and a:4, all of which have a b value of 0;
I've tried plotting this out on paper to see logically what I would do physically, but I just can't get my head around it, so a "For Dummies" answer would be really helpful. I thought I had learned enough to be employable, but this is really sticking me up, and it's just for a simple HTML5 canvas line graph. I'm getting data from a DB to compare two lines on the same graph, where there may not be data for one month for one type of data, but there is for the other type of data. And for those spots that don't exist in one or the other, I want to drop the line down to 0 on the Y axis, then back up to the next value. https://github.com/rmgreenstreet/custom-forms/blob/master/public/javascripts/canvasRender.js
Having just month indexes is not OK for proper sorting.
Just add some information about year and it will be done easily.
Without sorting it may look like:
// loop elements of the arr2 with reduce,
// if there is any element in arr1 with the same value of key 'a',
// result is the same as on the previous step
// if there is no elements of that kind, add new object {'a': arr2['a'], 'b' : 0} into arr1
function newArray (arr1, arr2) {
return arr2.reduce((result, obj2) => {
if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
return result;
}
return [...result, {['a'] : obj2['a'], 'b':0}];
}, arr1)
}
// now you can assign the result of newArray() to new variables
const arr1_ = newArray(arr1, arr2)
const arr2_ = newArray(arr2, arr1)
OP's final working function (having changed the a value to be a mm/yyyy string:
function equalize(arr1, arr2) {
let newArr = arr2.reduce(function (result, obj2) {
if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
return result;
}
return [...result, {'a' : obj2['a'], 'b':0}];
}, arr1);
newArr.sort(function (a, b) {
console.log(`a: ${a}`)
a = a.x.split('/');
b = b.x.split('/')
return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
});
return newArr;
};
The main annoyance of this task is checking for presence of items with certain values of a. A naive straightfoward solution would require iterating over arr2 for evey item of arr1 and vice versa, which makes it O(n2), i.e. slow.
An alternative approach suggests employing objects as fast lookup maps. The idea is to turn your array inside out, use as as keys and bs as values.
let arr1 = [{a:1, b:1},{a:2, b:3},{a:4, b:18},{a:5, b:2}]
let arr2 = [{a:2, b:2},{a:3, b:4},{a:4, b:8},{a:6, b:5},{a:7, b:1}]
// Using objects as lookup maps.
let m1 = {}
let m2 = {}
// Filling the maps.
// The 'a' becomes a key, the 'b' becomes a value.
arr1.forEach(v => m1[v.a] = v.b)
arr2.forEach(v => m2[v.a] = v.b)
// Iterating over the keys of m1, checking if m2 has that key,
// if not - adding it with a value of 0.
for (let f in m1) m2[f] || (m2[f] = 0)
// The same goes for m2 -> m1.
for (let f in m2) m1[f] || (m1[f] = 0)
// At this point both m1 & m2 have all the keys from both arrays without gaps.
let res1 = []
let res2 = []
// Assembling the resulting arrays.
for (let f in m1) res1.push({a: f, b: m1[f]})
for (let f in m2) res2.push({a: f, b: m2[f]})
Pardon my inclination for one-liners.
Here is my solution. I am using lodash for helper functions.
function combineArrays (a, b) {
Object.keys(b).forEach(function (k) {
const key = parseInt(k);
if (!a[key]) {
a[key] = b[key];
a[key].b = 0;
}
});
return _.values(a);
}
Working code snippet
// const arr1 = [{ a: 1, b: 1 }, { a: 2, b: 3 }, { a: 4, b: 18 }, { a: 5, b: 2 }];
// const arr2 = [{ a: 2, b: 2 }, { a: 3, b: 4 }, { a: 4, b: 8 }, { a: 6, b: 5 }, { a: 7, b: 1 }];
let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]
const arr1Map = _.keyBy(arr1, 'a');
const arr2Map = _.keyBy(arr2, 'a');
function combineArrays(a1Map, a2Map) {
const a = _.cloneDeep(a1Map);
const b = _.cloneDeep(a2Map);
Object.keys(b).forEach(function(k) {
const key = parseInt(k);
if (!a[key]) {
a[key] = b[key];
a[key].b = 0;
}
});
return _.values(a);
}
console.log(combineArrays(arr1Map, arr2Map));
console.log(combineArrays(arr2Map, arr1Map));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
You should loop through the first array, and check if each key is in the second array. If it's not you should insert an item using arr.splice().
If you know both lists are sorted, ie the keys are in order, then you can also don't need to check the whole array for the new key.
let j = 0;
for (let i = 0; i < arr1.length; i++) {
let possiblyMissingKey = arr1[i].a;
while (arr2[j].a < possiblyMissingKey && j < arr2.length)
j++;
if (arr2[j].a != possiblyMissingKey) {
let itemToInsert = {a:possiblyMissingKey, b:0};
arr2.splice(j, 0, itemToInsert);
}
}
After you go through the first array, do the second array.
My two arrays are:
const values = ['Master Clean', '45', '650']
const names = ['servicemenus.$.name', 'servicemenus.$.duration', 'servicemenus.$.cost']
The result should be like this:
{ 'servicemenus.$.name':'Master Clean', 'servicemenus.$.duration': '45', 'servicemenus.$.cost': 650}
Since I think that you know these two Arrays needs to be the same length at all time. This for loop could help you:
const values = ['Master Clean', '45', '650']
const names = ['servicemenus.$.name', 'servicemenus.$.duration', 'servicemenus.$.cost']
var obj = {}
for (var i = 0; i < names.length; i++) {
//or check with: if (values.length > i) { assignment }
obj[names[i]] = values[i];
}
console.log(obj);
Output will be this:
Object { servicemenus.$.name: "Master Clean", servicemenus.$.duration: "45", servicemenus.$.cost: "650" }
For completion, I found this Question could help you too: Merge two arrays into one Json object
You can work with the index of the array in a forEach to refer to the other and dynamically build the object keys:
const values = ['Master Clean', '45', '650']
const names = ['servicemenus.$.name', 'servicemenus.$.duration', 'servicemenus.$.cost']
let update = { };
names.forEach( (name,idx) => {
update[name] = values[idx];
});
And that gives you the result
From the assumption that the two arrays are always equal length, we can use one of them as the basis for a loop where we build the object:
let resultingObject = {};
names.forEach((name, i) => {
resultingObject[name] = values[i];
});
console.log(resultingObject);
You can reduce an array to a single value (object in your case). Reduce function accepts accumulator, current value and index which you can use to reference a value in the second array. Object.assign constructs an object with your keys/values.
const values = ['Master Clean', '45', '650'];
const names = ['servicemenus.$.name', 'servicemenus.$.duration', 'servicemenus.$.cost'];
const res = names.reduce((acc, cur, i) => Object.assign(acc, {[cur]: values[i]}), {});
console.log(res)
And with for in,loop through the object properties and assign it new object
var newobj = {};
for( var i in names){
newobj[names[i]] = values[i];
}
console.log(newobj);