Resolving simple references in a spreadsheet structure. Is this a linked list problem? - arrays

I have this job test task where I am need some help.
I have to somehow dynamically access the value in the data stucture below, through references. To this point I used loops and indexOf() in an ordered alphabet and numbers. indexOf("B") in alphabet is [[ 1 ]], indexOf(1) is [0] for the two dimensional array.
Here "B1" is referencing "C1", "C1" references "D1" .. to "H1" and when "H1" points to the text "Last", all of the formulas should turn into the same value - the text "Last".
But how? Been breaking my head for a couple of hours and remembered linked lists, but so far have no clue how to implement them. How can I achieve this?
{
data: [
[
{ reference: "B1" },
{ reference: "C1" },
{ reference: "D1" },
{ reference: "E1" },
{ reference: "F1" },
{ reference: "G1" },
{ reference: "H1" },
{ text: "Last" },
]
],
id: "job-20"
}

It looks like you need to work with a spreadsheet type of data structure, and need to recalculate cells based on the formulas they have.
You can use recursion for that.
The base case happens when you arrive at a cell that has no reference. In that case the text of that cell can be returned to the caller. And that caller will assign that text to the cell it was looking at, and also returns that to their caller...etc.
function get(reference) { // return the cell object at the given reference
return data[reference.slice(1)-1][reference.charCodeAt() - "A".charCodeAt()];
}
function resolve(cell, visited=new Set) {
// Have we found a cell with just text? Then return that to caller
if (!("reference" in cell)) return cell.text;
// Did we already meet this cell before? Then we are running in circles!
if (visited.has(cell)) return "Circular Reference!";
// Make a recursive call to know what the text should be
cell.text = resolve(get(cell.reference), visited.add(cell));
delete cell.reference;
return cell.text; // Return this value also to the caller
}
function calculate(data) {
// Get to each cell object...
for (let row of data) {
for (let cell of row) {
resolve(cell); // And update its text property by following references
}
}
}
let data = [
[
{reference: "B1"}, {reference: "C1"}, {reference: "D1"}, {reference: "E1"},
{reference: "F1"}, {reference: "G1"}, {reference: "H1"}, {text: "Last"},
]
];
calculate(data);
console.log(data);
It should be noted that in a real spreadsheet the references (formulas) are not deleted during such a recalculation. The cell will have both the text and the reference, so that when a cell's text is updated, all other dependent cells get their own text updated accordingly again.

Related

Why is my array.find and array.filter returning empty

I have an Array that looks like this
resultList: any[];
this.resultList = [
{
"id": "14e6f101-f8e8-4914-930f-cbba7a9c5328",
"value": "Dream Inc."
},
{
"id": "9a16c1c0-68f3-498a-b968-61849ccc2a21",
"value": "Dressing, Inc. ABC LOREBOX SERVICES"
},
{
"id": "919b3cdb-c5fb-40c8-b88f-6c7f44f8446f",
"value": "Dresson-Brand Company"
}
]
I am having a hard time trying to retrieve the second item (index 1) by using the value. I can get the other two items by value but the second item returns undefined
code I am using
search(value: any) {
//value coming in
//Dressing, Inc. ABC LOREBOX SERVICES
console.log('*** value to search ***', value);
var foundObj = this.resultList.find(p => p.value == value);
console.log('*** foundObj ***', foundObj);
}
foundObj comes back empty and same results when I do a filter. Any idea's what is wrong with that string that it can't be found? It seems I can get any other string (this is a dynamic array) but this one.
The issue came from the dataList I was using. In the element I was missing the 'value' attribute. Once I added that the spaces were no longer removed and my filtering was able to pick it up.

trying to push two specific values into another array as a key value pair using typescript

Newbie here and this is a project I'm building to learn. I'm going around in circles so forgive my ignorance please. I'm now not even sure that what I want to do is possible. I also understand that there are probably better ways to achieve my ultimate goal but this is what I have.
I have an array that includes some user input.
"participants": [ {
"name": "Cristina",
"email": "cristina#gmail",
"yourPerson": "Richard",
"spouseEmail": "Richard#gmail" } ] }
I want to pull the "name" and "youPerson" values and use them as a key:value pair. So name would be the key and yourPerson would be the value.
I thought I could use a forEach but no matter what I do I either get an undefined array or I copy the entire array, not just those two fields.
here is my code at the moment:
participantArray = [];
namePlusSpouseArray = [];
submitParticipant() {
this.participantArray.push(this.participantForm.value);
console.log(this.participantArray)
this.createNamePlusSpouseArray();
}
createNamePlusSpouseArray() {
this.participantArray.forEach(name => {
this.namePlusSpouseArray.push(this.participantArray[name]);
console.log(this.namePlusSpouseArray)
});
}
Not sure if you want a result array of key value pairs, or you want 1 object/map/dictionary/lookup of name -> youPerson
Assuming you want an array containing key value pairs, you can use map
this.namePlusSpouseArray = this.participantArray.map(participant => ({
[participant.name]: participant.youPerson
});
If you want a lookup of name -> youPerson, the "namePlusSpouseArray" shouldn´t be an array but instead just an object
namePlusSpouseLookup = {};
this.participantArray.forEach(participant => {
this.namePlusSpouseLookup[participant.name] = participant.youPerson;
});
The simplest solution is:
const participantArray = {
"participants": [ { "name": "Cristina", "email": "cristina#gmail", "yourPerson": "Richard", "spouseEmail": "Richard#gmail" } ] };
const createPair = participants => {
return participants.map(participant =>
({ [participant.name]: participant.yourPerson}))
}
console.log(createPair(participantArray.participants));

Add subelement to JSON array

I have the following code where I design the format of a JSON-array dynamically from variables ==>
var Title = '"text_title"'
var Topic2 = '"text_topic2"'
var jsonData = [ ];
createWantedJSON("title", data[i].topic, jsonData)
function createWantedJSON(title, Topic2, arr) {
arr.push({
"Topic": title,
[Topic2] : {
"Topic3": [{
"Subitem1": "Text1",
"Subitem2": "Text2",
"Subitem3": "Text3"
}]
}
}
This goes fine for the key and value which are not nested. But I don't know how to make it dynamic for the content of Topic3. I tried making a variable with the following content =>
'"Subitem1": "Text1", "Subitem2": "Text2", "Subitem3": "Text3"' but then of course it sees the content as one string and not as elements of the nested Topic3 array. I guess this isn't that hard but I can't seem to fix it.

Add data to array within array in MongoDB

So heres my mongodb document:
{
"_id" : "",
"lists" : [
{
"name" : "list 1",
"items" : []
},
{
"name" : "list 2",
"items" : []
}
]
}
How would I go about adding an object inside "items"?
This is the code I have so far, but it doesn't work:
xxx.update(_id, {$push: { "lists.$.items": item}});
Note that I have access to the index (variable called 'index'), so its possible to insert an item at index, 0, 1, 2..., etc.
I tried this before, but it won't work:
xxx.update({_id, "lists": index}, {$push: { "lists.$.items": item}});
I also looked at other similar questions and couldn't find anything. Most of them have some sort of id field in their arrays, but I don't.
What about
xxx.update({_id}, {$push: { "lists.index.items": item}});
Of course this would fail, what I mean is replace index with real index values
xxx.update({_id}, {$push: { "lists.2.items": item}});
You can manipulate the update json based on the index maybe as below.
var update = '{$push: { "lists.'+index+'.items": '+item+'}}';
var updateObj = JSON.parse(update);
xxx.update({_id}, updateObj);
Not sure if it will work as it is or it would need further tweaking, but you get the idea.

mongodb - adding the value in a field to the value in an embedded array

I have a document in MongoDB as below.
{
"CorePrice" : 1,
"_id" : 166,
"partno" : 76,
"parttype" : "qpnm",
"shipping" :
[
{
"shippingMethod1" : "ground",
"cost1" : "10"
},
{
"shippingMethod2" : "air",
"cost2" : "11"
},
{
"shippingMethod3" : "USPS",
"cost3" : "3"
},
{
"shippingMethod4" : "USPS",
"cost4" : 45
}
]
}
My goal is to add CorePrice (1) to cost4 (45) and retrieve the computed value as a new column "dpv". I tried using the below query. However I receive an error exception: $add only supports numeric or date types, not Array. I'm not sure why. Any kind of help will be greatly appreciated.
db.Parts.aggregate([
{
$project: {
partno: 1,
parttype: 1,
dpv: {$add: ["$CorePrice","$shipping.cost1"]}
}
},
{
$match: {"_id":{$lt:5}}
}
]);
When you refer to the field shipping.cost1 and shipping is an array, MongoDB does not know which entry of the shipping-array you are referring to. In your case there is only one entry in the array with a field cost1, but this can't be guaranteed. That's why you get an error.
When you are able to change your database schema, I would recommend you to turn shipping into an object with a field for each shipping-type. This would allow you to address these better. When this is impossible or would break some other use-case, you could try to access the array entry by numeric index (shipping.0.cost1).
Another thing you could try is to use the $sum-operator to create the sum of all shipping.cost1 fields. When there is only one element in the array with a field cost1, the result will be its value.
I am able to achieve this by divorcing the query into two as below.
var pipeline1 = [
{
"$unwind": "$shipping"
},
{
$project:{
partno:1,
parttype:1,
dpv:{
$add:["$CorePrice","$shipping.cost4"]
}
}
},
{
$match:{"_id":5}
}
];
R = db.tb.aggregate( pipeline );

Resources