Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
From this:
[["a", "b"], ["a", "c"], ["a", "d"], ["d", "e"], ["d", "f"], ["f", "g"]]
To this:
[["a", "b"], ["a", "c"], ["a", "d", "e"], ["a", "d", "f", "g"]]
The first element of each inner array represents a "father" and the second one a "son", so the final goal is to find grandsons, grandgrandsons... and then group them in bigger arrays, where all descendants are together.
Maybe it's an easy task, but I've been struggling to figure out how to get it!
If you like to get all relations, without parts which are included in other results, you could get an object of all descendant and start with the parents who are not having parents.
let
getNodes = k => parents[k]
? parents[k].flatMap(getNodes).map(a => [k, ...a])
: [[k]],
data = [["a", "b"], ["a", "c"], ["a", "d"], ["d", "e"], ["d", "f"], ["f", "g"]],
parents = {},
children = new Set,
result;
for (const [p, c] of data) {
(parents[p] ??= []).push(c);
children.add(c);
}
result = Object
.keys(parents)
.filter(p => !children.has(p))
.flatMap(getNodes);
result.map(a => console.log(...a));
Related
I have REST API endpoint that accepts page, limit (page size) and returns (for simplicity) sorted letters of alphabet (A, B, C, ... Z). Example call of this endpoint is:
let items = await api.items.get({ page: 0, size: 3 })
// items = ["A", "B", "C"]
Now let's say I have implemented infinite scroll and when user scrolls at the of the area, I want to load another 3 items:
const newItems = await api.items.get({ page: 1, size: 3 })
items = [...items, ...newItems]
// items = ["A", "B", "C", "D", "E", "F"]
Everything is fine, however what if user deletes some items, eg. "B" and "D"?
// items = ["A", "C", "E", "F"]
How can I fetch another page of 3 items from correct offset?
const newItems = await api.items.get({ page: 2, size: 3 })
items = [...items, ...newItems]
// items = ["A", "C", "E", "F", "I", "J", "K"] - "G" and "H" has been skipped
Are there any common techniques for this? Unfortunately, I can't modify the API, so I have to use page and size only.
I have this array of arrays, where the inner arrays are uniformly structured (“tuple-like”) with a unique ID (a string) and a non-unique integer:
[
["A",2],
["B",1],
["C",1]
]
I need the JavaScript function to create the list of permutations below, that does not permute tuples with the same integer value:
[
["A", "B", "C"],
["B", "A", "C"],
["B", "C", "A"]
]
Quoting user pilchard in the comments below, I'm trying to permute “by the second index and avoid duplicates”.
The list should therefore not include these permutations:
[
["A", "C", "B"], // integers same as in ["A", "B", "C"]
["C", "A", "B"], // integers same as in ["B", "A", "C"]
["C", "B", "A"] // integers same as in ["B", "C", "A"]
]
Also, it is preferable to avoid “movement” inside the array. Therefore, ["A", "B", "C"] is a better permutation than ["A", "C", "B"]
In the simplest scenario, the input could be this:
[
["A",1],
["B",1],
["C",1],
["D",1]
]
The result should simply be 1 permutation, as opposed to the 24 that is the result when also permuting identical integers:
[
["A", "B", "C", "D"]
]
Again, “movement” inside the array should be avoided, so ["A", "B", "C", "D"] is the preferred alternative.
Instead of operating on an array of characters, operate on an array of groups of characters. You can take any of these solutions, and instead of removing the chosen character from the input to put it into the output, remove the first character of the chosen group and remove the group only when it's empty.
function groupPermutations(groups) {
if (!groups.length) return [[]];
return groups.flatMap((group, i) => {
// assert(group.length > 0)
const [val, ...rest] = group;
const remaining = rest.length
? [...groups.slice(0,i), rest, ...groups.slice(i+1)]
: [...groups.slice(0,i), ...groups.slice(i+1)];
return groupPermutations(remaining).map(p => [val, ...p]);
});
}
console.log(groupPermutations(["A", "BC"]));
console.log(groupPermutations(["ABCD"]));
Now you only need a trivial conversion of your tuple input format to the grouping:
const pairs = [
["A",2],
["B",1],
["C",1],
];
const byInteger = new Map();
for (const [val, key] of pairs) {
if (!byInteger.has(key)) byInteger.set(key, []);
byInteger.get(key).push(val);
}
const groups = Array.from(byInteger.values());
console.log(groupPermutations(groups));
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
hello I have an array of strings with values in a list, I mean, the only valid values are "a", "b", "c"
In general with it's "a" it's "a" during some time, so, what I want to know is the indexes they changed.
For example:
const myList = ["a", "a", "a", "a", "a", "a", "c", "c", "c", "c", "b", "b"]
const result = //returns [6,10]
You just loop through elements and compare the current element with the previous one.
const myList = ["a", "a", "a", "a", "a", "a", "c", "c", "c", "c", "b", "b"]
const result = [];
myList.map((el, index) => {
return myList[index-1] !== el && index > 0 && result.push(index)
})
console.log(result)
How can I remove multiple items by index and save the removed items. I get the currently selected values from a ListBox (e.g.selectedValues = [1, 4, 2]) and have two arrays actives availables. I try to move the selected elements in an efficient way.
That's how I would solve this:
var actives = [ "a", "d", "k", "e"]
var availables = [ "m", "o", "v" ]
var selectedValues = [3, 1]
var elementsToMove = []
selectedValues.forEach(i => {
elementsToMove.push(actives[i])
})
actives = actives.filter(item => !elementsToMove.includes(item))
availables = availables.concat(elementsToMove);
console.log(actives);
console.log(availables);
Expected output:
actives = [ "a", "k" ]
availables = [ "m", "o", "v", "e", "d"]
Note: The length of the arrays can be very large.
A .filter with an .includes inside is O(n ^ 2). For very large inputs, this could be an issue. Consider converting the elementsToMove into a Set instead, turning the overall computational complexity to O(n). You can also construct the elementsToMove array much more concisely by using .map instead of forEach followed by push:
var actives = [ "a", "d", "k", "e"]
var availables = [ "m", "o", "v" ]
var selectedValues = [3, 1];
const elementsToMove = selectedValues.map(i => actives[i]);
const elementsToMoveSet = new Set(elementsToMove);
actives = actives.filter(item => !elementsToMoveSet.has(item))
availables = availables.concat(elementsToMove);
console.log(actives);
console.log(availables);
You could take a single loop and psuh the spliced elements to the other array.
var actives = [ "a", "d", "k", "e"],
availables = [ "m", "o", "v" ],
selectedValues = [3, 1];
selectedValues.forEach(i => availables.push(...actives.splice(i, 1)));
console.log(actives);
console.log(availables);
This question already has answers here:
Access nested objects via array of property names
(2 answers)
Closed 6 years ago.
Imagine I have an array, which looks like:
const x = ["a", "b", "c", "d"]
I wish to use it in order to navigate an object that I don't know the structure of, like:
const y = {
"a": {
"b": {
"c": {
"d": "Value I require"
}
},
"f": ["g", "h"]
},
"e": null
}
However, my issue is that I don't know how deep y will be, or how many indices are in the array x. How do I do the following:
let someVariable = {"prefilled": "data"}
someVariable[x[0]][x[1]][x[2]][x[3]] = y[x[0]][x[1]][x[2]][x[3]]
In a way which is neither specific to the length of x, the depth of y (and also preferably isn't my current solution, which is a case statement upto a depth of 6)? For this simplified case, someVariable should hopefully look as follows:
{
"prefilled": "data",
"a": {
"b": {
"c": {
"d": "Value I require"
}
}
}
}
I would either use a tool like Lodash's _.get or implement something similar that can navigate an object:
let _ = require('lodash');
const x = ["a", "b", "c", "d"]
_.get(object, x.join('.'))
You could iterate the array and walk the object.
const getValue = (object, path) => path.reduce((o, k) => (o || {})[k], object),
y = { a: { b: { c: { d: "Value I require" } }, f: ["g", "h"] }, e: null },
x = ["a", "b", "c", "d"]
console.log(getValue(y, x));