using array for URLSearchParams in vue3 - arrays

i want to append key and value of array , using for axos request
here is the array
const
schedule = ref({
"userId" : 13,
"sunday" : ["mornig","afternoon","nigh"],
"monday" : ["afternoon","nigh"],
"wednesday" : ["mornig","afternoon"]
})
to append manuallya i can do like this
params.append("userId",data.value.userId)
params.append("sunday[0]",data.value.sunday[0])
params.append("sunday[1]",data.value.sunday[1])
params.append("sunday[2]",data.value.sunday[2])
params.append("monday[0]",data.value.monday[0])
params.append("monday[1]",data.value.monday[1])
params.append("wednesday[0]",data.value.wednesday[0])
params.append("wednesday[1]",data.value.wednesday[1])
but this will be problim if length of the schedule time l (morning,night ...) unknown
i do like this
let i = 0
for(let j in data.value){
console.log(j+$[i++])
}
and also loop using for in and for of , but none of them are success

You "just" need to do a nested iteration. Loop through object, and if any value is an array, loop through the array. Here's an example code to flatten the dataset. Just note that instead of flattenData(schedule) you'd need to pass the ref's value with flattenData(schedule.value).
const schedule = {
userId: 13,
sunday: ["mornig", "afternoon", "nigh"],
monday: ["afternoon", "nigh"],
wednesday: ["morning", "afternoon"],
};
function flattenData(data) {
const o = {};
Object.keys(data).forEach((dataKey) => {
if (Array.isArray(data[dataKey])) {
data[dataKey].forEach(
(_, nestedArrayIndex) =>
(o[`${dataKey}[${nestedArrayIndex}]`] =
data[dataKey][nestedArrayIndex])
);
} else {
o[dataKey] = data[dataKey];
}
});
return o;
}
// show flattened data
console.log(flattenData(schedule));
// prepare params
const params = new URLSearchParams("");
// populate
Object.entries(flattenData(schedule)).forEach(([k,v]) => params.append(k, v))
// result:
console.log(params.toString())

Related

How correctly copy and modify an array in typescript?

I'm trying to copy an array, replace some elements in it and then replace the original array with the copy containing the new elements.
Here's my code:
type Span = {
start: number
end: number
}
const handleSplitClick = (span: Span, tag: string) => {
let copy = props.value.map(a => {return{...a}})
const splitIndex = copy.findIndex(s => s.start === span.start && s.end === span.end)
if (splitIndex != -1 ){
const tagIndex = (copy[splitIndex] as any).tags.findIndex((t:string) => t == tag)
if (tagIndex > -1){
(copy[splitIndex] as any).tags.splice(tagIndex, 1)
console.log(copy)
console.log(props.value)
}
}
}
Here's how props.value looks:
I'm trying to modify the tags array within props.value.
I tried to initialise the copy of the array in these ways:
//1
let copy = props.value.map(a => {return{...a}})
//2
let copy = [...props.value]
//3
let copy = props.value.map(a => Object.assign({}, a));
Regardless of what I do, when I try to remove the particular element from tags:
(copy[splitIndex] as any).tags.splice(tagIndex, 1)
Both the original props.value and copy get modified.
How can I correctly achieve this?
Thanks.
It looks like you want to create a new array where you've removed the matching tag from the tags array when its start and end match, and that you want to do this immutably (that is, without changing the original array or original element object, like a state update in React and similar). To do that, in map return the other elements unchanged, and return a new element with the updated tags for the one that matches:
const handleSplitClick = (span: Span, tag: string) => {
// Use `map` to create the new array
const copy = props.value.map((element) => {
// Is this the element we want to update?
if (element.start === span.start && element.end === span.end) {
// Yes, return an updated copy with the first tag removed
return {
...element,
tags: element.tags.filter((t) => t !== tag),
};
}
// No, just return the element unchanged
return element;
});
// ...use or return `copy`...
};
Or if you prefer keeping things really terse:
const handleSplitClick2 = (span: Span, tag: string) => {
// Use `map` to create the new array
const copy = props.value.map((element) =>
element.start === span.start && element.end === span.end
? {
...element,
tags: element.tags.filter((t) => t !== tag),
}
: element
);
// ...use or return `copy`...
};
Note that in the vast majority of cases, you don't need or want type annotations on the callback parameters for map or filter; TypeScript will infer them correctly:
Live version with TypeScript commented out:
const props = {
value: [
{start: 0, end: 1, tags: ["a", "b", "c"]},
{start: 1, end: 2, tags: ["a", "b", "c"]},
// ^^^ The one we'll target
{start: 2, end: 3, tags: ["b", "c"]},
]
}
const handleSplitClick = (span/*: Span*/, tag/*: string*/) => {
// Use `map` to create the new array
const copy = props.value.map((element) => {
// Is this the element we want to update?
if (element.start === span.start && element.end === span.end) {
// Yes, return an updated copy with the first tag removed
return {
...element,
tags: element.tags.filter((t) => t !== tag),
};
}
// No, just return the element unchanged
return element;
});
console.log(JSON.stringify(copy, null, 4));
};
handleSplitClick({start: 1, end: 2}, "b");
.as-console-wrapper {
max-height: 100% !important;
}

Creating and pushing elements in an new array depends on conditions

My Data Array
data:[
0:{
id:1 ,.....
competetion:[
0:{
id: 1....,
match:[
0:{id: 1 ......},
1:{same}
.
.
]
1:{same}]},
2:{same}
.
.
]
},
1:{same},
2:{same}
.
.
.
]
For data[] i able to create a new array(sportarr[]) with pushing elements but i want to create for the same as competetion[] and match[] in the same array sportarr[]
If there any other way to do it please Help me...
My Code: Here i am looping it:
this.sportsSidebar = response.data; // My data Array (this.sportsSidebar)
const arrlength = response.data.length;
for (let i = 0; i < arrlength; i++) {
this.sportarr.push({ // I declared a new array where i want to push the element
id: i,
value: false
});
}
if you want your own content based on the mapping what I will suggest is that first iterate through the array then map each match and competetion and write your own logic inside the map
const arrlength = data.length;
for (let i = 0; i < arrlength; i++) {
let competition = [];
competition = data[i].competetion.map( (val, index) => {
#write your own logic to produce the required outcome
return {
id: index,
value: false
};
});
this.sportarr.push({
id: i,
value: false,
competetion: competition
});
console.log('myarrr...', this.sportarr);
i Appriciate Pathikrit Sanyal and Fahd Lihidheb For the ansers
Here Is my Change according to Pathikrit Sanyal
for (let i = 0; i < arrlength; i++) {
let competition = [];
competition = response.data[i].competetion.map((val, index) => {
let match = [];
match = val.match.map((value, indx) => {
return {
id: indx,
value: false
};
});
return {
id: index,
value: false,
match
};
});
this.sportarr.push({
id: i,
value: false,
competetion: competition
});
console.log('myarrr...', this.sportarr);
}
Now i am getting what i wanted
i am not sure if you are trying to create an array for each nasted array (competetion and match) or not, but here you go
this.sportsSidebar = response.data; // My data Array (this.sportsSidebar)
const competetionList = // Array of competetions
[].concat.apply([], this.sportsSidebar.map(item => item.competetion));
const matchList = // Array of matchs
[].concat.apply([], competetionList .map(item => item.match));
}

ES6: Merge two arrays into an array of objects

I have two arrays that I want to merge together to one array of objects...
The first array is of dates (strings):
let metrodates = [
"2008-01",
"2008-02",
"2008-03",..ect
];
The second array is of numbers:
let figures = [
0,
0.555,
0.293,..ect
]
I want to merge them to make an object like this (so the array items match up by their similar index):
let metrodata = [
{data: 0, date: "2008-01"},
{data: 0.555, date: "2008-02"},
{data: 0.293, date: "2008-03"},..ect
];
So far I do this like so: I create an empty array and then loop through one of the first two arrays to get the index number (the first two arrays are the same length)... But is there an easier way (in ES6)?
let metrodata = [];
for(let index in metrodates){
metrodata.push({data: figures[index], date: metrodates[index]});
}
The easiest way is probably to use map and the index provided to the callback
let metrodates = [
"2008-01",
"2008-02",
"2008-03"
];
let figures = [
0,
0.555,
0.293
];
let output = metrodates.map((date,i) => ({date, data: figures[i]}));
console.log(output);
Another option is to make a generic zip function which collates your two input arrays into a single array. This is usually called a "zip" because it interlaces the inputs like teeth on a zipper.
const zip = ([x,...xs], [y,...ys]) => {
if (x === undefined || y === undefined)
return [];
else
return [[x,y], ...zip(xs, ys)];
}
let metrodates = [
"2008-01",
"2008-02",
"2008-03"
];
let figures = [
0,
0.555,
0.293
];
let output = zip(metrodates, figures).map(([date, data]) => ({date, data}));
console.log(output);
Another option is to make a generic map function which accepts more than one source array. The mapping function will receive one value from each source list. See Racket's map procedure for more examples of its use.
This answer might seem the most complicated but it is also the most versatile because it accepts any number of source array inputs.
const isEmpty = xs => xs.length === 0;
const head = ([x,...xs]) => x;
const tail = ([x,...xs]) => xs;
const map = (f, ...xxs) => {
let loop = (acc, xxs) => {
if (xxs.some(isEmpty))
return acc;
else
return loop([...acc, f(...xxs.map(head))], xxs.map(tail));
};
return loop([], xxs);
}
let metrodates = [
"2008-01",
"2008-02",
"2008-03"
];
let figures = [
0,
0.555,
0.293
];
let output = map(
(date, data) => ({date, data}),
metrodates,
figures
);
console.log(output);
If you use lodash, you can use zipWith + ES6 shorthand propery names + ES6 Arrow functions for a one-liner, otherwise see #noami's answer.
const metrodata = _.zipWith(figures, metrodates, (data, date)=> ({ data, date }));

Lodash: how to split the array of objects using some separator object

Considering I'm having the array:
var arr = [
{type:'a', name:'a1'}, {type:'b', name:'b1'}, {type:'hr'},
{type:'a', name:'a2'}, {type:'b', name:'b2'}, {type:'hr'},
{type:'a', name:'a3'}, {type:'b', name:'b2'}, {type:'hr'}
]
I'd split it into array of arrays of objects using {type:'hr'} object as separator element. So the result is:
[
[{type:'a', name:'a1'}, {type:'b', name:'b1'}],
[{type:'a', name:'a3'}, {type:'b', name:'b2'}],
[{type:'a', name:'a3'}, {type:'b', name:'b3'}]
]
Think lodash is useful for it?
Currently I've used _.map for this:
var result = [], sub = []; _.map(tokens, (it, idx) => { if(it.type === 'hr'){
result.push(sub);
sub = [];
} else {
sub.push(it);
}
});
if(sub.length){
result.push(sub);
}
console.log(result);
You could use reduce and create a new sub-array when you find {type:'hr'}:
var arr = [
{type:'a', name:'a1'}, {type:'b', name:'b1'}, {type:'hr'},
{type:'a', name:'a2'}, {type:'b', name:'b2'}, {type:'hr'},
{type:'a', name:'a3'}, {type:'b', name:'b2'}, {type:'hr'}
];
var delimiter = { type: 'hr' };
var res = _.reduce(arr, function(result, obj, index) {
if (_.isEqual(obj, delimiter)) {
if (index !== arr.length - 1) result.push([]);
} else {
_.last(result).push(obj);
}
return result;
}, [[]]);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Here's what I would do:
function splitBy(array, predicate, result = []) {
const taken = _.takeWhile(array, predicate);
const remaining = _.tail(_.dropWhile(array, predicate));
return remaining.length ?
splitBy(remaining, predicate, result.concat([taken])) :
result.concat([taken]);
}
splitBy(
arr,
_.negate(_.partial(_.isEqual, { type: 'hr' })))
);
The idea is to use takeWhile() to get the items that don't match the separator. Then, dropWhile() creates the next chunk of array to iterate over by passing it to splitBy().
The actual predicate that's used to determine what the separator is is passed in as an argument, meaning that you can reuse this function for other kinds of separators.

What is the Best way to loop over an array in scala

I'm new to scala and I'm trying to refactor the below code.I want to eliminate "index" used in the below code and loop over the array to fetch data.
subgroupMetricIndividual.instances.foreach { instanceIndividual =>
val MetricContextListBuffer: ListBuffer[Context] = ListBuffer()
var index = 0
contextListBufferForSubGroup.foreach { contextIndividual =>
MetricContextListBuffer += Context(
entity = contextIndividual,
value = instanceIndividual(index).toString
)
index += 1
}
}
For instance, if the values of variables are as below:
contextListBufferForSubGroup = ("context1","context2")
subgroupMetricIndividual.instances = {{"Inst1","Inst2",1},{"Inst3","Inst4",2}}
Then Context should be something like:
{
entity: "context1",
value: "Inst1"
},
{
entity: "context2",
value: "Inst2"
},
{
entity: "context1",
value: "Inst3"
},
{
entity: "context2",
value: "Inst4"
}
Note:
instanceIndividual can have more elements than those in contextListBufferForSubGroup. We must ignore the last extra elements in instanceIndividual in this case
You can zip two lists into a list of tuples and then map over that.
e.g.
subgroupMetricIndividual.instances.foreach { instanceIndividual =>
val MetricContextListBuffer = contextListBufferForSubGroup.zip(instanceIndividual).map {
case (contextIndividual, instanceIndividualIndex) => Context(
entity = contextIndividual,
value = instanceIndividualIndex.toString
)
}
}
If Context can be called like a function i.e. Context(contextIndividual, instanceIndividualIndex.toString) then you can write this even shorter.
subgroupMetricIndividual.instances.foreach { instanceIndividual =>
val MetricContextListBuffer = contextListBufferForSubGroup
.zip(instanceIndividual.map(_.toString)).map(Context.tupled)
}
Without knowing your exact datatypes, I'm mocked up something which is probably close to what you want, and is slightly more functional using maps, and immutable collections
case class Context(entity:String, value:String)
val contextListBufferForSubGroup = List("context1","context2")
val subgroupMetricIndividualInstances = List(List("Inst1","Inst2",1),List("Inst3","Inst4",2))
val result: List[Context] = subgroupMetricIndividualInstances.map { instanceIndividual =>
contextListBufferForSubGroup.zip(instanceIndividual) map { case v: (String, String) =>
Context(
entity = v._1,
value = v._2
)
}
}.flatten

Resources