in Object.keys(obj) works only part time - javascript

Im trying to look if a number is in the Object.keys() for some reason I get a partial response some of the numbers are not included in the final object. Any idea why in works only partially here?
var arrayOfNumbersIHave = [
"542009988",
"7411111111",
"542261111",
"542009988",
"7411111111",
"7411111111",
"7442334675",
"661766029",
"692549335",
]
var snapObject = {
"542009988": "A",
"542261111": "B",
"661766029": "C",
"6617666029": "D",
"692549335": "E",
"7442334675": "F",
"7411111111": "G",
}
var objToDisplay = {};
for (const i in arrayOfNumbersIHave) {
if (i in Object.keys(snapObject)) {
objToDisplay[arrayOfNumbersIHave[i]] = snapObject[arrayOfNumbersIHave[i]]
}
}
console.log(objToDisplay)
Result:
{
"542009988": "A",
"542261111": "B",
"7442334675": "F",
"7411111111": "G",
}
Expected result:
{
"542009988": "A",
"542261111": "B",
"661766029": "C",
"692549335": "E",
"7442334675": "F",
"7411111111": "G",
}

You can avoid using for..in to iterate an array. Alternatively you can use reduce on the arrayOfNumbersIHave & in each iteration curr parameter will represent each element of arrayOfNumbersIHave. Use this curr to check if there exist a key by same name in snapObject. Is so then in the accumulator object add the key and value
let arrayOfNumbersIHave = [
"542009988",
"7411111111",
"542261111",
"542009988",
"7411111111",
"7411111111",
"7442334675",
"661766029",
"692549335",
]
let snapObject = {
"542009988": "A",
"542261111": "B",
"661766029": "C",
"6617666029": "D",
"692549335": "E",
"7442334675": "F",
"7411111111": "G",
}
let objToDisplay = arrayOfNumbersIHave.reduce(function(acc, curr) {
if (snapObject[curr]) {
acc[curr] = snapObject[curr]
}
return acc;
}, {}) // {} is accumulator object
console.log(objToDisplay)

Using the in operator in that manner is not quite correct. in checks for either properties in objects or indices in an array. So it is probably returning true only when the number you are checking happens to be an index in the array.
So for this case, you really want to omit the Object.keys and instead use:
for (const i in arrayOfNumbersIHave) {
if (arrayOfNumbersIHave[i] in snapObject) {
objToDisplay[arrayOfNumbersIHave[i]] = snapObject[arrayOfNumbersIHave[i]]
}
}
And as #adiga points out below, we can simplify this with a for...of loop, to get:
for (const val of arrayOfNumbersIHave) {
if (val in snapObject) {
objToDisplay[val] = snapObject[val];
}
}

You need to check the value of the array, if this is in the object, not by taking an index and look if the index is in an array.
This line
if (arrayOfNumbersIHave[i] in snapObject) {
takes the value of arrayOfNumbersIHave[i] as key for checking with in operator and an object.
var arrayOfNumbersIHave = ["542009988", "7411111111", "542261111", "542009988", "7411111111", "7411111111", "7442334675", "661766029", "692549335"],
snapObject = { 542009988: "A", 542261111: "B", 661766029: "C", 6617666029: "D", 692549335: "E", 7442334675: "F", 7411111111: "G" },
objToDisplay = {};
for (const i in arrayOfNumbersIHave) {
if (arrayOfNumbersIHave[i] in snapObject) {
objToDisplay[arrayOfNumbersIHave[i]] = snapObject[arrayOfNumbersIHave[i]];
}
}
console.log(objToDisplay);

You can just simply iterate on first array, and check if the current item has any presence in snapObject, if so, just create an entry (key) in your objToDisplay and assign matched value:
arrayOfNumbersIHave.forEach(function(number) {
if (snapObject[number]) objToDisplay[number] = snapObject[number];
});

Related

How to get the differences between two arrays in JavaScript, including moved items

I have two arrays, which represent two versions of the same array, and I would like to know the difference between them.
Unlike earlier questions, I would also like to know about items that merely moved. If an item is in both arrays, but it's in different places, I'd like to know about it. Additionally, I do not want items in the result diff that only moved because other items were added or removed, which of course causes all following items to change indices. I only consider items to have moved, if they changed their relative position to each other.
let old = [ "b", "c", "d", "e", "f", "g", "h", "i", "j" ];
let news = [ "a", "d", "c", "e", "f", "h", "i", "j" ];
// algo should result in
let added = [ "a" ];
let removed = [ "b", "g" ];
let moved = [ "d", "c" ];
let old = [ "b", "c", "d", "e", "f", "g", "h", "i", "j" ];
let news = [ "a", "d", "c", "e", "f", "h", "i", "j" ];
let added = news.filter(item => !old.includes(item));
let removed = old.filter(item => !news.includes(item));
// find items that only changed place
let oldCommon = old.filter(item => news.includes(item));
let newCommon = news.filter(item => old.includes(item));
let moved = newCommon.filter((item, i) => item != oldCommon[i]);
console.log("added", added);
console.log("removed", removed);
console.log("moved", moved);
This solution also deals with duplicate problems.
let oldArray = [ "b", "c", "d", "e", "f", "g", "h", "i", "j" ];
let newArray = [ "a", "d", "c", "e", "f", "h", "i", "j" ];
let added = newArray.filter(function(item) {
return oldArray.indexOf(item) === -1;
});
let removed = oldArray.filter(function(item) {
return newArray.indexOf(item) === -1;
});
let moved = newArray.filter(function(item) {
return oldArray.indexOf(item) !== -1 &&
newArray.indexOf(item) !== -1 &&
oldArray.indexOf(item) !== newArray.indexOf(item);
});
console.log(added);
console.log(removed);
console.log(moved);
The added and removed elements should be clear.
For the moved elements we have to keep track of the indexes, based on the added and removed elements.
I loop over the newArray and if I find an added element I mark it's index with -1 and I'll continue the indexing where I left i.e.: [0, 1, -1, 2, 3]
In the case of the removed elements if I find a removed index then I'll increase the current and all of the following indexes i.e.: if the removed index is 5 then [0,1,2,3,4,5,6,7,8] becomes [0,1,2,3,4,6,7,8,9].
Finally I just loop over the newWithIndexes and compare the indexes (that I calculated) with the oldArrays indexes.
let oldArray = [ "b", "c", "d", "e", "f", "g", "h", "i", "j" ];
let newArray = [ "a", "d", "c", "e", "f", "h", "i", "j" ];
let added = newArray.filter(item => oldArray.indexOf(item) == -1);
let removed = oldArray.filter(item => newArray.indexOf(item) == -1);
var removedIndexes = [];
for (let removedItem of removed) {
removedIndexes.push(oldArray.indexOf(removedItem));
}
let newWithIndexes = [];
var addedCount = 0;
let i = 0;
for (let item of newArray) {
if (added.includes(item)) {
newWithIndexes.push({el: item, index: -1});
addedCount++;
} else {
newWithIndexes.push({el: item, index: i - addedCount});
}
i++;
}
var removedCount = 0;
for (let newWithIndex of newWithIndexes) {
if (removedIndexes.includes(newWithIndex.index + removedCount)) {
removedCount++;
}
if (newWithIndex.index != -1) {
newWithIndex.index += removedCount;
}
}
let moved = [];
for (let newWithIndex of newWithIndexes) {
if (newWithIndex.index != oldArray.indexOf(newWithIndex.el)) {
moved.push(newWithIndex.el);
}
}
console.log(added);
console.log(removed);
console.log(moved);

how to filter Loop through an array in JavaScript

I have a table, I try to put the data of the array into the table
for example:
var myArray = ["A","B","C","101","D","E","F","201","G","H","I","101"];
for (var i = 0; i < myArray.length; ; i++) {
var newArray= myStringArray[i];
//Do something
}
The following looks like
Now I want to display only table4=101, what can I do?
I try to put if inside for
var myArray = ["A","B","C","101","D","E","F","201","G","H","I","101"];
for (var i = 0; i < myArray.length; ; i++) {
var newArray= myStringArray[i];
if(table4.equals(101){
//Do something
}
}
But not working, I still got all the data.
How can I modify it?
Thank you
I would first suggest that you convert your flat array into a 2-dimensional array, so instead of:
["A","B","C","101","D","E","F","201","G","H","I","101"];
we have:
[
[ "A", "B", "C", "101" ],
[ "D", "E", "F", "201" ],
[ "G", "H", "I", "101" ]
];
This will make working with the array much easier.
We can easily convert between the two like this:
let array2d = [];
for (let i = 0; i < myArray.length; i += 4 /* this is the row length */) {
array2d.push(myArray.slice(i, i + 4));
}
This will create are two-dimensional array.
Now, to filter by a certain value:
const onlyRowsMatching101 = array2d.filter(row => row[3] === "101");
More information on array filter
Here is your solution
var result = [];
var myArray = [
[ "A", "B", "C", "101" ],
[ "D", "E", "F", "201" ],
[ "G", "H", "I", "101" ]
];
myArray.forEach(function (item) {
if(item[item.length-1] === '101')
result.push(item);
});
console.log(result);
if you organize your data into smart data, you will have much more success with your code. imagine if your data looked like this:
var myArray = [
{ id: 1, tab1: "A", tab2: "B", tab3: "C", tab4: "101"},
{ id: 2, tab1: "D", tab2: "E", tab3: "F", tab4: "201"},
{ id: 3, tab1: "G", tab2: "H", tab3: "I", tab4: "101"}
];
you would have much more success displaying and manipulating it.

How to define id of Object generated from 2D Array

I have generated an object from 2D array.
And then, how to define unique id through each object?
"?" in the following code needs to edit.
data = [
["a", "b", "c"],
["a", "b"]
]
for (i in data) {
data[i] = data[i].map(c => ({id: ?, char:c}) )
}
console.log(data)
The following result format is assumed.
[
0: {
0:{
"id": "?",
"char": "a"
},
1:{
"id": "?",
"char": "b"
},
2:{
"id": "?",
"char": "c"
}
},
1: {
0:{
"id": "?",
"char": "a"
},
1:{
"id": "?",
"char": "b"
}
}
]
I thought iterating, but it seems like to needs to flatten the object,
so I could not use it because I did not want to change the format of the original object.
You can create count variable to make the id
data = [
["a", "b", "c"],
["a", "b"]
]
let count = 0;
for (let i in data) {
data[i] = data[i].map(c => {
count ++;
return {id: count, char:c}
} )
}
console.log(data)
You could map single objects inside and assign the arrays to an object. Take the same approach for the outer array.
var data = [["a", "b", "c"], ["a", "b"]],
result = Object.assign(
{},
data.map(a => Object.assign(
{},
a.map(char => ({ id: '?', char }))
))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Because you want objects rather than arrays, you won't be able to use .map. Because you have both parent objects and nested objects, you might use reduce twice:
const data = [
["a", "b", "c"],
["a", "b"]
];
const output = data.reduce((a, arr, i) => {
a[i] = arr.reduce((obj, char, j) => {
obj[j] = { char, id: '?' };
return obj;
}, {});
return a;
}, {});
console.log(output);

Convert an array to nested object using Lodash, is it possible?

I have an array:
["a", "b", "c", "d"]
I need to convert it to an object, but in this format:
a: {
b: {
c: {
d: 'some value'
}
}
}
if var common = ["a", "b", "c", "d"], I tried:
var objTest = _.indexBy(common, function(key) {
return key;
}
);
But this just results in:
[object Object] {
a: "a",
b: "b",
c: "c",
d: "d"
}
Since you're looking for a single object out of an array, using _.reduce or _.reduceRight is a good candidate for getting the job done. Let's explore that.
In this case, it's going to be hard to work from left to right, because it will require doing recursion to get to the innermost object and then working outward again. So let's try _.reduceRight:
var common = ["a", "b", "c", "d"];
var innerValue = "some value";
_.reduceRight(common, function (memo, arrayValue) {
// Construct the object to be returned.
var obj = {};
// Set the new key (arrayValue being the key name) and value (the object so far, memo):
obj[arrayValue] = memo;
// Return the newly-built object.
return obj;
}, innerValue);
Here's a JSFiddle proving that this works.

Sorting an Array of JavaScript Objects a Specific Order (using existing function)

Given an array of objects:
{
key: "a",
value: 42
},
{
key: "d",
value: 28
},
{
key: "c",
value: 92
},
{
key: "b",
value: 87
}
and an array of keys:
["c", "a", "b", "d"]
Is there a ECMAScript function or a 3rd-party JavaScript library that lets you sort - in one line/function call - the first array of objects, to match the order of the keys specified in the second array, such that the result is:
{
key: "c",
value: 92
},
{
key: "a",
value: 42
},
{
key: "b",
value: 87
},
{
key: "d",
value: 28
}
Other questions that provide a function or algorithm:
Javascript - sort array based on another array - Stack Overflow
javascript - How do I sort an array of objects based on the ordering of another array? - Stack Overflow
Similar/related questions:
Sorting an Array of Objects in PHP In a Specific Order
php - Sort array of objects
Just use indexOf to convert the key to the correct order:
var order = ["c", "a", "b", "d"];
_.sortBy(arr, function(obj){
return _.indexOf(order, obj.key);
});
Fiddle
If there are a lot of keys, then it would be advantageous to make a hash-map out of the array, like:
var order = ["c", "a", "b", "d"];
var orderMap = {};
_.each(order, function(i) { orderMap[i] = _.indexOf(order, i); });
This makes the key-sorting lookup constant time rather than O(n). (Fiddle)
Great answers provided so far. Thought that the following may also be an alternative solution in plain JS:
var arr = arr.sort(function(a,b) {
return order.indexOf( a.key ) - order.indexOf( b.key );
//for the sake of recent versions of Google Chrome use:
//return a.key.charCodeAt(0) > b.key.charCodeAt(0); or return a.key.charCodeAt(0) - b.key.charCodeAt(0);
});
var arr = [
{
key: "a",
value: 42
},
{
key: "d",
value: 28
},
{
key: "c",
value: 92
},
{
key: "b",
value: 87
}
];
var order = ["c", "a", "b", "d"];
console.log( 'Original: ', JSON.stringify( arr ) );
var arr = arr.sort(function(a,b) {
return order.indexOf( a.key ) - order.indexOf( b.key );
});
console.log( 'Ordered: ', JSON.stringify( arr ) );
const obj = [
{
key: "a",
value: 42
},
{
key: "d",
value: 28
},
{
key: "c",
value: 92
},
{
key: "b",
value: 87
}
]
const sortList = ["c", "a", "b", "d"];
const sortedObj = obj.sort((a, b) => {
return (
sortList.indexOf(a.key) - sortList.indexOf(b.key)
);
});
console.log(sortedObj );
I can't claim that this is the most efficient way, but you can use the key for each object as a key for properties in another object. Then simply access them by these keys.
for (x = 0; x < objn.length; x++) {
newobj[objn[x].key] = objn[x];
}
objn = [];
for (x = 0; x < keys.length; x++) {
objn.push(newobj[keys[x]]);
}
console.log(objn);
http://jsfiddle.net/WdehF/
// create hash map el.key -> index, to help us with direct access, avoid searching
const hashMap = arr.reduce((acc, el, index) => { acc[el.id] = el; return acc }, {})
// finally, map the ids to the final result
const ids.map(id => hashMap[id])
const data = [{key:"a"},{key:"d"},{key:"c"},{key:"b"}] // <-your data
const order = ["c", "a", "b", "d"] // <-create an array in the order you wish
const orderedArray = order.map(char=>data.find(res=>res.key===char)) // <- what you want
For each char in order: it will map if the char is equal to any key found within your data, and return it, consecutively

Categories

Resources