Nested synchronous loops in NodeJS - javascript

So I have an array of object that I want to use for my server, each object has the same amount of keys.
Here is a simplified version of the array:
[{
"BTQ": 1,
"COLLIC": "Foo1",
"MMC": "Bar1",
"PTURE": 39,
"STOCK": 6,
},
{
"BTQ": 1,
"COLLIC": "Foo1",
"MMC": "Bar2"",
"PTURE": 31,
"STOCK": 2,
},
{
"BTQ": 2,
"COLLIC": "Something1",
"MMC": "AnotherThing1",
"PTURE": 40,
"STOCK": 5,
},
{
"BTQ": 2,
"COLLIC": "Something1",
"MMC": "AnotherThing1",
"PTURE": 11,
"STOCK": 7,
}]
and I want to build a function that loops through all of these objects, and builds another JSON array that looks like that:
[
{
"BTQ": 1,
"COLLICs": {
"Foo1": {
"Bar1": {
"Stock": 6,
"PTURE" {"39": 6}
},
"Bar2": {
"Stock": 2,
"PTURE": {"31": 2,}
}
}
}
},
{
"BTQ": 2,
"COLLICs": {
"Something1": {
"AnotherThing1": {
"Stock": 12,
"PTURE": {"40": 5, "11": 7}
}
}
}
},
//etc ...
]
I am using NodeJS, and I figured out I needed to build a function like this one :
function step(i){
if (i < raw.length){
data.push(raw[i].A);
step(i + 1);
} else {
console.log("Finished");
console.log(data);
}
}
but the thing is I don't know how to nest this function...
Here is what I want to achieve in the end:
1) Loop through each object in the raw array (done with the function above)
2) For each object, loop through data (the sorted array) and see if any of the objects in there has the same "BTQ" value, if so : go into the object, and see if the raw[i].COLLIC exists the data[j].COOLLICs' keys. If exists, look if the MMC exists, ETC ... If any of the values does not exist, create a new key/object which stores all the informations, and then start again with the following raw object.
It is probably not very clear and I'm sorry for that, if it can help, I had built the same algorithm but with for loops, I can paste it here if it could help to make things clearer.
I really hope you can help me because I'm loosing my mind on this ...
Thanks ! Ali

Related

How to get JSON entry from returned objects

I got JSON data, like:
{
"id": 1,
"active": true,
"dependency": [
{ "id": 2 }
{ "id": 3 }
]
},
{
"id": 2,
"active": true
},
{
"id": 3,
"active": true
}
I want to retrieve the "active" value for each dependency in the id 1 object. So far I used a forEach to get those dependency.
thisElement.dependency.forEach(function(id) {
console.log(id)
}
Which returns id 2 and id 3 as objects. Is there a way to use id.active straight away? By using only one loop? Because the result so far are objects without any connection to the related JSON data. Would it require to loop through the whole JSON data to retrieve those values?
The most efficient thing to to is create a hashmap with an Object or Map first so you only need to iterate the array once to find dependency related values.
You could do it by using Array#find() to search whole array each time but that is far more time complexity than the o(1) object lookup
const activeMap = new Map(data.map(obj => [obj.id, obj.active]))
data[0].dependency.forEach(({id}) => console.log(id ,' active: ' , activeMap.get(id)))
<script>
const data =
[
{
"id": 1,
"active": true,
"dependency": [
{"id": 2 },
{"id": 3}
]
},
{
"id": 2,
"active": false
},
{
"id": 3,
"active": true
}
]
</script>

algorithm reorder list of objects

I am searching for an algorithm to reorder an list of dictionarys or in javascript array of objects.
For example I have the following list of objects:
my_dict = [
{
"id": 123,
"priority": 1
},
{
"id": 234,
"priority": 2
},
{
"id": 345,
"priority": 3
},
{
"id": 654,
"priority": 4
}
]
Now I want to change the item with id 654 to be the first priority. So the other items gets automatically to priority 2,3 and 4.
This should be the result:
my_dict = [
{
"id": 654,
"priority": 1
}
{
"id": 123,
"priority": 2
},
{
"id": 234,
"priority": 3
},
{
"id": 345,
"priority": 4
},
]
Another example is when I want to decrease the priority of item 234 to priority 3 then the item with priority 3 should become priority 2 (from the original/first dict). There are should no priority be twice in this list and there should not be gaps.
my_dict = [
{
"id": 123,
"priority": 1
},
{
"id": 345,
"priority": 2
},
{
"id": 234,
"priority": 3
},
{
"id": 654,
"priority": 4
}
]
For clarification here is an other example.
If I move item with id 123 to priority 4 the item before should become priority 1,2 and 3.
my_dict = [
{
"id": 234,
"priority": 1
},
{
"id": 345,
"priority": 2
},
{
"id": 654,
"priority": 3
}
{
"id": 123,
"priority": 4
},
]
The list should always start with priority 1. Can somebody explain how I can implement it with python or javascript? I tried it with a for loop starting and 1 but this does not work.
The discussions about a better data structure are spot-on. But if you still want to implement what you asked for, we can write a straightforward JS version that does the naive thing:
const changePriority = (xs, id, to,
idx = xs .findIndex (({id: i}) => i == id),
ys = [...xs .slice (0, idx), ...xs .slice (idx + 1)]
) =>
[ ...ys . slice (0, to - 1), xs [idx], ...ys .slice(to - 1)]
.map ((x, i) => ({...x, priority: i + 1}))
const dict = [{id: 123, priority: 1}, {id: 234, priority: 2}, {id: 345, priority: 3}, {id: 654, priority: 4}]
console .log (
changePriority (dict, 654, 2)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
Note that this depends upon your id and the new priorty, to actually existing in the input. It wouldn't be hard to add error-checking.
Also note that this returns a new array, and doesn't mutate the original; we're not barbarians here.
I disagree with the idea of having priority be represented by both the position in the list and the "priority" member. This is redundant and will cause trouble at some point.
Further, I have to make assumptions to answer this question, as the question is not complete.
Assumptions:
In the end, the list should be sorted by priority again
Priorities should end up being integers
Priorities always start at 1 and enumerate the list without gaps
First approach
Specify exactly where you want to put your item by using halfs. This is simple and everything else should fall in place.
Example
Task: Move 234 to priority 3.
Sadly, it is not uniquely defined what this is supposed to mean, as it is unclear where the old item of priority 3 should move to.
Instead move it to priority 3.5 to make it unambiguous, then re-sort and re-enumerate:
# Change priority of '234' to '3.5'
my_dict[1]["priority"] = 3.5
# Sort
my_dict.sort(key=lambda x: x["priority"])
# Re-enumerate
for (position, item) in enumerate(my_dict):
item["priority"] = position + 1
print(my_dict)
[{'id': 123, 'priority': 1}, {'id': 345, 'priority': 2}, {'id': 234, 'priority': 3}, {'id': 654, 'priority': 4}]
For large datasets this is really slow though, as every single priority change is O(n*log(n)), as it requires a sort.
You should investigate in better data structures, like a heap or a linked list, depending on your exact usage scenario.
Second approach
If we remove the 'priority' member, we can write a much more efficient algorithm:
def move(data, original, target):
data.insert(target, data.pop(original))
# Important: Start priorities at 0, not 1. This makes this a lot easier.
my_dict = [123, 234, 345, 654]
move(my_dict, 3, 0)
print(my_dict)
my_dict = [123, 234, 345, 654]
move(my_dict, 1, 2)
print(my_dict)
[654, 123, 234, 345]
[123, 345, 234, 654]
https://ideone.com/o9UcCb
For a longer discussion about how to move an item inside of a list, read this discussion.

How to check for duplicated inside this JSON Array in JavaScript?

I need a way to check if a Server already exist inside my JSON Array.
Here is an example JSON Array:
[{
"ID": 14,
"PID": 15728,
"Online": 1,
"Servers": "staging,dev,test"
}, {
"ID": 9,
"PID": 6048,
"Online": 1,
"Servers": ""
}, {
"ID": 8,
"PID": 13060,
"Online": 1,
"Servers": "ubuntu,test"
}, {
"ID": 7,
"PID": 15440,
"Online": 1,
"Servers": "main"
}]
I need a JavaScript function to handle this.
Example calls could be:
checkForDupes("staging") -> true
checkForDupes("debian") -> false
checkForDupes("ubuntu") -> true
checkForDupes("test") -> true
You may use some() and includes() methods or arrays and split() method of string:
let data = [
{"ID": 14, "PID": 15728, "Online": 1, "Servers": "staging,dev,test"},
{"ID": 9, "PID": 6048, "Online": 1, "Servers": ""},
{"ID": 8, "PID": 13060, "Online": 1, "Servers": "ubuntu,test"},
{"ID": 7, "PID": 15440, "Online": 1, "Servers": "main"}
];
function checkForDupes(d, s) {
return d.some(o => o["Servers"].split(",").includes(s));
}
console.log(checkForDupes(data, "staging"));
console.log(checkForDupes(data, "debian"));
console.log(checkForDupes(data, "ubuntu"));
console.log(checkForDupes(data, "test"));
Description:
.some() will run the test function against each object and return true if
any one object passes the test.
.split() will create an array from string of "Servers" property delimited by ,
.includes() will check where the passed name exists in array or not returning true or false as appropriate.
Useful Resources:
Array.prototype.some()
Array.prototype.includes()
String.prototype.split()
Arrow Functions
var checkdupe = function(param) {
var count = [];
for(i=0;i<json.length;i++)
{
if(json[i].Servers.split(',').indexOf(param) != -1)
{
count.push(json[i].ID);
}
}
if(count.length>1){
return true;
}
}
you can use that count array to get more detail
indexOf might be the best choice rather than contains or includes, if it comes to a point where speed matters

elasticsearch autosuggest returning tricky JSON

I'm running a node.js server that sends queries to an elasticsearch instance. Here is an example of the JSON returned by the query:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 9290,
"max_score": 0,
"hits": []
},
"suggest": {
"postSuggest": [
{
"text": "a",
"offset": 0,
"length": 1,
"options": [
{
"text": "Academic Librarian",
"score": 2
},
{
"text": "Able Seamen",
"score": 1
},
{
"text": "Academic Dean",
"score": 1
},
{
"text": "Academic Deans-Registrar",
"score": 1
},
{
"text": "Accessory Designer",
"score": 1
}
]
}
]
}
}
I need to create an array containing each job title as a string. I've run into this weird behavior that I can't figure out. Whenever I try to pull values out of the JSON, I can't go below options or everything comes back as undefined.
For example:
arr.push(results.suggest.postSuggest) will push just what you'd expect: all the stuff inside postSuggest.
arr.push(results.suggest.postSuggest.options) will come up as undefined even though I can see it when I run it without .options. This is also true for anything below .options.
I think it may be because .options is some sort of built-in function that acts on variables, so instead of seeing options as JSON and is instead trying to run a function on results.suggest.postSuggest
arr.push(results.suggest.postSuggest.options)
postSuggest is an array of object.options inside postSuggest is also array of object. So first you need to get postSuggest by postSuggest[0] and then
postSuggest[0].options to get array of options
This below snippet can be usefule
var myObj = {..}
// used jquery just to demonstrate postSuggest is an Array
console.log($.isArray(myObj.suggest.postSuggest)) //return true
var getPostSuggest =myObj.suggest.postSuggest //Array of object
var getOptions = getPostSuggest[0].options; // 0 since it contain only one element
console.log(getOptions.length) ; // 5 , contain 5 objects
getOptions.forEach(function(item){
document.write("<pre>Score is "+ item.score + " Text</pre>")
})
Jsfiddle

How to sort an array of objects in ascending order of number?

I have an array of objects like the following :
var array = {
"112" : {
"id": "3",
"name": "raj"
},
"334" : {
"id": "2",
"name": "john"
},
"222" : {
"id": "5",
"name": "kelvin"
}
}
Now i want to sort the array in ascending order of id and then restore it in array. I tried using sort() but could not do it. Please help how to do so that when i display the data from the array it comes sorted.
Assuming you meant your code to be an array of objects, ie:
var unsortedArray = [
{ id: 3, name: "raj" },
{ id: 2, name: "john" },
{ id: 5, name: "kelvin" }
];
Then you would be able to sort by id by passing a function to Array.sort() that compares id's:
var sortedArray = unsortedArray.sort(function(a, b) {
return a.id - b.id
});
As others have pointed out, what you have is an object containing objects, not an array.
var array = {
"112" : {
"id": "3",
"name": "raj"
},
"334" : {
"id": "2",
"name": "john"
},
"222" : {
"id": "5",
"name": "kelvin"
}
}
var sortedObject = Array.prototype.sort.apply(array);
result:
{
"112": {
"id": "3",
"name": "raj"
},
"222": {
"id": "5",
"name": "kelvin"
},
"334": {
"id": "2",
"name": "john"
}
}
That isn't an array, it is an object (or would it if it wasn't for the syntax errors (= should be :)). It doesn't have an order.
You could use an array instead (making the current property names a value of a key on the subobjects).
Alternatively, you could use a for loop to build an array of the key names, then sort that and use it as a basis for accessing the object in order.
JavaScript objects are unordered by definition. The language specification doesn't even guarantee that, if you iterate over the properties of an object twice in succession, they'll come out in the same order the second time.
If you need things to be ordered, use an array and the Array.prototype.sort method.
That is an object but you can sort an array ilke this:
Working Demo: http://jsfiddle.net/BF8LV/2/
Hope this help,
code
function sortAscending(data_A, data_B)
{
return (data_A - data_B);
}
var array =[ 9, 10, 21, 46, 19, 11]
array.sort(sortAscending)
alert(array);​
Not many people knows that Array.sort can be used on other kinds of objects, but they must have a length property:
array.length = 334;
Array.prototype.sort.call(array, function(a, b) {return a.id - b.id;});
Unfortunately, this doesn't work well if your "array" is full of "holes" like yours.

Categories

Resources