Nodejs difference between two paths - node.js

I am trying to get the difference between two path. I've come with a solution, but I am not really happy about it, even if it works. Is there a better / easier way to do this?
var firstPath = '/my/first/path'
, secondPath = '/my/first/path/but/longer'
// what I want to get is: '/but/longer'
// my code:
var firstPathDeconstruct = firstPath.split(path.sep)
, secondPathDeconstruct = secondPath.split(path.sep)
, diff = []
secondPathDeconstruct.forEach(function(chunk) {
if (firstPathDeconstruct.indexOf(chunk) < 0) {
diff.push(chunk)
}
})
console.log(diff)
// output ['but', 'longer']

Node provides a standard function, path.relative, which does exactly this and also handles all of the various relative path edge cases that you might encounter:
From the online docs:
path.relative(from, to)
Solve the relative path from from to to.
Examples:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb')
// returns
'..\\..\\impl\\bbb'
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
// returns
'../../impl/bbb'

Related

populate object properties using lambda expression in typescript

Newbie Alert! I feel silly asking this question but I need someone to teach me the correct syntax.
I have code that looks like this:
let thing: INewThing;
thing.personId = another.personId;
thing.address = another.work.address;
thing.greades = another.subjectInfo.grades;
thing.isCurrent = another.student.isCurrent;
I know it can be written cleaner. I want to use a lamda expression, something like this:
let thing: INewThing => {
personId = another.personId,
address = another.work.address,
grades = another.subjectInfo.grades,
isCurrent = another.student.isCurrent
} as IThingUpdate;
I have looked and looked for an example. I have yet to find one that works for me. It's just syntax but no matter what I try it doesn't work.
You're just looking to create a new object, which is a pretty different thing from a "lambda" (function). Just declare the object. You don't need a function.
const thing = {
personId: another.personId,
address: another.work.address,
// use the correct spelling below - no 'greades'
grades: another.subjectInfo.grades,
isCurrent: another.student.isCurrent,
};
If the another is typed properly, that should be sufficient.
If the another object had more properties using the same path, another option would be to destructure those properties out, then declare the object with shorthand, eg:
const originalObj = { prop: 'val', nested: { foo: 'foo', bar: 'bar', unwanted: 'unwanted' } };
const { foo, bar } = originalObj.nested;
const thing = { foo, bar };
Destructuring like this, without putting the values into differently-named properties, helps reduce typos - if a property starts out, for example, as someLongPropertyName, putting it into a standalone identifier someLongPropertyName and then constructing an object with shorthand syntax ensures that the new object also has the exact property name someLongPropertyName (and not, for example, someLongPRopertyName - which isn't that uncommon of a mistake when using the more traditional object declaration format).
But since all the paths in your another object are different, this approach wouldn't work well in this particular situation.

Importing a modified String class from another file in nodejs

I have added to the String class three prototype classes on a file classed parse.js:
String.prototype.parseCropTo = function (needle) {
if (this.includes(needle) === false) return false;
return this.slice(0, this.indexOf(needle)).trim();
}
String.prototype.parseCropFrom = function (needle) {
if (this.includes(needle) === false) return false;
return this.slice(this.indexOf(needle) + needle.length).trim();
}
String.prototype.parseCropBetween = function (needleFrom, needleTo) {
let haystack = this.parseCropFrom(needleFrom);
if (haystack != false) return haystack.parseCropTo(needleTo);
}
As far as I can see, imported files have to expose specific functions and then they are called via a variable. However, I wish to import parse.js to other files so I could use these functions directly on strings:
let haystack = 'This is a lovely day';
console.log(haystack.parseCropBetween('is', 'day'));
Is this possible? thanks in advance.
By extending the prototype of String, you will have these methods on every string you'll ever use, however you need to load it somewhere in your code, because you won't be able to use that beforehand.
The reason that works is because your'e accessing String.prototype by reference, as with all non-primitive types in javascript so calling it once, will get you set for the rest of your code.
Generally speaking, it's not advised to extend native constructs.
See full example here:
https://codesandbox.io/s/epic-cerf-4qshv?file=/src/App.js
Additionally, I'd advise you to read some opinions about extending prototypes in javascript and considers the pros and cons of this approach:
Why is extending native objects a bad practice?

Node module for finding file paths with multiple possible roots

Is there a Node module which allows you to specify multiple roots, give it a file, and it tries to find the file?
A know a lot of libraries/modules do this sort of thing, but my Google-fu failed to turn up an existing module for it, which was kind of surprising.
To clarify, basically if I had some config like this:
roots: ['node_modules', 'bower_components', 'src']
And I asked it to find "my-file.js", it would search the following:
node_modules/my-file.js
bower_components/my-file.js
src/my-file.js
And return the first one that resolves to an existing file, or return an error saying it couldn't resolve it.
I dont know any library for this either, but what youre asking for can be done in a few lines of code :
const fs = require('fs');
const path = require('path');
const roots = ['node_modules', 'bower_components', 'src'];
const myFile = 'my-file.js';
const result = roots.map(root => path.resolve(path.join(root,myFile))).map(fs.existsSync);
This will give you an array of true/false values corresponding to each element in roots. So if src/my-file.js and node_modules/my-file.js exist, you would get result as
[true, false, true]

How to get the path between 2 nodes using Breadth-First Search?

I am trying to find a path between two nodes in a graph, where the edges are unweighted.
I am using a Breadth First Search, which stops when it finds the target, in order to find the existence of a path, but I am not sure how to get the path itself.
I tried looking at the list of visited nodes, but this did not seem to help.
I saw someone answer this question using prolog, but I am a C++ programmer.
I also looked at Dijkstras algorithm, but this seems like over kill, since a simple Breadth-first Search has got me almost the whole way.
How to get the path between 2 nodes using Breadth-First Search?
In your node struct, you add a variable called parentNode which is the parent of that node in the path. In the end, you can retrieve the path by traversing from the goal node backward.
I found this simple algorithm which stores the path to the node along with the node in the queue here: https://stackoverflow.com/a/50575971/5883177
So when we pop a node from the queue, we also get the path to that node readily.
The code in the link is in python which uses tuples to store the pair. Here is a C++ implementation of the same which uses std::pair.
bool findPath(Node *n1, Node *n2, vector<Node*> &path)
{
// We use queue to perform a BFS traversal and in addition to storing the
// node we'll also store the path so far to the node.
queue<pair<Node*,vector<Node*>>> q;
// Visit the first node and add it to the queue.
n1->visited=1;
// Form the path, create a pair and add it the queue.
vector<Node*> p;
p.push_back(n1);
q.push(make_pair(n1,p));
while(!q.empty())
{
pair<Node*,vector<Node*>> curPair = q.front();
q.pop();
// visit all the unvisited nodes and check if there is n2 in it.
for(Node *u : curPair.first->adjNodes ){
if(u->visited == 0){
if(u->value == n2->value){
// found our destination. Return true
// form the path by appending this node to the path till now
curPair.second.push_back(u);
// update the passed 'path' vector with the path so far.
path = curPair.second; // all nodes will be copied into path
return true;
}
// Not our node, visit the node if unvisited
if(u->visited == 0){
u->visited = 1;
// Create a new path with this node added.
// Path so far can be obtained from the pair in queue
vector<Node*> newPath(curPair.second);
newPath.push_back(u);
// Add the node and the path to it into the queue.
q.push(make_pair(u, newPath));
}
}
}
}
return false;
}
class Node{
public:
Node(int val)
{
value = val;
visited=0;
}
int value;
vector<Node*> adjNodes;
int visited;
};

Multiple Greasemonkey Metablocks

I'm trying to write a Greasemonkey script for a hierarchy of websites such that I have a bunch of code modifications for http://www.foo.com/*, then more specific ones for http://www.foo.com/bar/*, and still others for http://www.foo.com/foobar/*.
Is there anyway for me to write all these in the same script, or do I have to make multiple?
Is there anyway for me to write all
these in the same script, or do I have
to make multiple?
Yes, just use those three #includes, then in your user script do something like (depends on specifics of script):
var currentURL = (document.location+'');
if (currentURL .match(/http:\/\/www\.foo\.com\/foobar\/.*/)) {
// do stuff for page set A
} else if (currentURL .match(/http:\/\/www\.foo\.com\/foo\/.*/)) {
// do stuff for page set B
} else if (currentURL .match(/http:\/\/www\.foo\.com\/.*/)) {
// do stuff for page set C
}
One nifty trick I was shown for dealing with different functions at different sub-locations is to use the global directory of function names as a sort of virtual switchboard...
// do anything that is supposed to apply to the entire website above here.
var place = location.pathname.replace(/\/|\.(php|html)$/gi, "").toLowerCase();
// the regex converts from "foo/" or "foo.php" or "foo.html" to just "foo".
var handler;
if ((handler = global["at_" + place])) {
handler();
}
// end of top-level code. Following is all function definitions:
function at_foo() {
// do foo-based stuff here
}
function at_foobar() {
// do foobar stuff here.
}

Resources