I'm trying to do something interesting in JavaScript, but I can't. This is my input:
var Input = ['a','a','a','b','b','b','b','c','c','c','a','a','c','d','d','d'];
So my output is that only get differents values and go in a new vector.
var Output = SomeFunction(Input);
This is what I want:
Output = ['a','b','c','a','c','d'];
Y tried with this, but don't work aswell:
function SomeFunction(input){
var out= [];
for (var i = 0; i < input.length - 1; i++) {
if(input[i] == input[i+1]){
out.push(input[i]);
}
}
return out;
}
You can use filter()
var input = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'a', 'a', 'c', 'd', 'd', 'd'];
input = input.filter(function(v, i, arr) {
return arr[i - 1] !== v;
//compare with the previous value
})
document.write(JSON.stringify(input));
You can use backreferencing regex
Convert the array to string by using join, so that regex can be used on it
Use backreferencing regex to remove the consecutive elements with replace()
Convert back the string to array using split
(\w)\1* Explanation
var input = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'a', 'a', 'c', 'd', 'd', 'd'];
var str = input.join('');
input = str.replace(/(\w)\1*/g, '$1').split('');
console.log(input);
document.write('<pre>' + JSON.stringify(input, 0, 2) + '</pre>');
You can do a filter like
var Input = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'a', 'a', 'c', 'd', 'd', 'd', 'e'];
var Output = SomeFunction(Input);
function SomeFunction(input) {
var out = input.filter(function(value, i) {
return value !== input[i + 1]
});
return out;
}
output.innerHTML = JSON.stringify(Output)
<pre id="output"><pre>
Try like this
var out= [];
var i = 0;
for (i = 0; i < input.length - 1; i++) {
if(input[i] != input[i+1]){
out.push(input[i]);
}
}
if (out[out.length-1] !== input[i])
out.push(input[i]);
How about this:
var Input = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'a', 'a', 'c', 'd', 'd', 'd'];
function SomeFunction(input) {
var out = [];
var initStr = input[0];
console.log(initStr)
for (var i = 1; i < input.length; i++) {
if (input[i] === initStr) {
} else {
out.push(input[i - 1]);
initStr = input[i];
}
}
out.push(input[i - 1]);
console.log(out);
}
SomeFunction(Input)
function SomeFunction(input) {
var out= [];
out.push(input[i]);
for (var i = 0; i < input.length - 1; i++) {
if(input[i] !== out[out.length-1]){
out.push(input[i]);
}
}
return out;
}
Worked for me:
function SomeFunction(input){
var out= [];
for (var i = 0; i < input.length; i++) {
if(input[i] !== input[i+1]){
out.push(input[i]);
}
}
return out;
}
Be careful with the name of the varible "input". It's not "Input", it's "input".
Example using array filters.
Pretty simple as long as the array is not too large and could rather easily be extended to compare some property in an array of objects. With a larger array it might be faster though to do a for loop instead as in some of the other answers.
var Input = ['a', 'b', 'c','a', 'b', 'a', 'b', 'c','c']
var Output = Input.filter(function(value,index) { return Input[index - 1] != value; });
var Input = ['a','a','a','b','b','b','b','c','c','c','a','a','c','d','d','d'];
var Output = SomeFunction(Input);
function SomeFunction(input){
var out= [];
for (var i = 1; i < input.length; i++) {
if(input[i] != input[i-1]){
out.push(input[i-1]);
}
}
out.push(input[input.length - 1]);
return out;
}
alert(Output);
Related
This may be a duplicate question. But I didn't find any similar questions in this forum.
I'm trying to modify values in an array to different format.
arrayInput = ['A', 'B', 'C', 'D', 'E', 'F'];
arrayOutput= ['A;B', 'C;D', 'E;F'];
I got the solution with the following approach
let arrayInput = ['A', 'B', 'C', 'D', 'E', 'F']
arrayOutput = [arrayInput[0]+';'+ arrayInput[1], arrayInput[2]+';'+ arrayInput[3]];
if (arrayInput[4]) {
let val = arrayInput[4] + (arrayInput[5] ? ';'+arrayInput[5] : '');
arrayOutput.push(val);
}
console.log(arrayOutput);
But I am looking for a generic solution such that even if I have more items in array, it should generate the output in desired format.
['A', 'B', 'C', 'D', 'E', 'F', 'G'] ==> ['A;B', 'C;D', 'E;F', 'G']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] ==> ['A;B', 'C;D', 'E;F', 'G;H']
Thanks for the support
You can use Array#reduce as in the following demo. Just in case there's an odd number of elements, I have included a test here ${arr[i+1] ? ";" + arr[i+1] : ""}; otherwise use ${arr[i+1]}, if you always have an even number of elements.
const arrayInput = ['A', 'B', 'C', 'D', 'E', 'F'],
arrayOutput = arrayInput.reduce(
(acc,cur,i,arr) =>
i % 2 === 0 ?
[...acc,`${cur}${arr[i+1] ? ";" + arr[i+1] : ""}`] :
acc,
[]
);
console.log( arrayOutput );
//OUTPUT: ['A;B', 'C;D', 'E;F'];
Use a for loop, and increment it by 2 every iteration:
const arrayInput = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
const res = [];
for (let i = 0; i < arrayInput.length; i += 2) {
const part1 = arrayInput[i];
const part2 = arrayInput[i + 1];
if (part1) {
res.push(part1 + (part2 ? (';' + part2) : ''));
}
}
console.log(res);
You can try something like this (implementation based on array reduce and join):
const arrayInput = ['A', 'B', 'C', 'D', 'E', 'F'];
let temp = [];
const output = arrayInput.reduce((accumulator, item) => {
if (temp.length < 2) {
temp.push(item);
} else {
accumulator.push(temp.join(';'));
temp = [];
}
return accumulator;
}, []);
console.log(output)
Using a foreach :
let arrayInput = ['A', 'B', 'C', 'D', 'E', 'F','G','H','I']
let newArray = [];
arrayInput.forEach((e,i) => {
if((i + 1)%2==0)
{
newArray[newArray.length -1] = `${newArray[newArray.length -1]};${e}`
}
else
{
newArray.push((i + 1) < newArray.length ? `${e};` : e)
}
});
console.log(newArray)
For example:
const items = ['a', 'a', 'b', 'a', 'a'];
Would become:
['a', 'b', 'a']
Is there a clean way of doing the above using JS?
I have tried:
const items = ['a', 'a', 'b', 'a', 'a'];
const uniqueInRow = [];
for (var i=0; i < items.length; i++) {
item = items[i];
if (item !== item[i++]) {
uniqueInRow.push(item);
}
}
console.log(uniqueInRow);
Try like following:
const items = ['a', 'a', 'b', 'a', 'a'];
const res = []
for(let i = 0; i < items.length; i++) {
if (i === 0 || items[i] !== items[i-1]) res.push(items[i])
}
console.log(res)
You may avoid equal neighbours via oneliner:
vals.forEach((v, i) => (i < vals.length && v === vals[i + 1]) && vals.splice(i, 1))
Say you have the following array:
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
How would you change this array so that all the "b" items get grouped together, until you hit another "a".
So the result of the above array would look like:
['a', 'a', 'bbb', 'a', 'bb', 'a'];
I'm trying to solve a problem with wrapping span tags around words that match a patter in a React app, but this is essentially my problem.
I've been working at it for ages but can't come up with anything I'm happy with.
Any ideas?
Cheers.
Count repeating occurences, then build the result based on that:
const result = [];
let curr = array[0], count = 1;
for(const el of array.slice(1).concat(undefined)) {
if(el !== curr || el !== "b") {
result.push(curr.repeat(count));
curr = el, count = 1;
} else count++;
}
Assuming the elements will always be single letters, you can merge the elements, then match on either bs or non-bs:
ab.join('').match(/(b+|.)/g)
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
let output = ab.join('').match(/(b+|.)/g);
console.log(output);
Using Array#reduce you could do something like this.
I'm assuming the first two characters in your solution were a typo.
const data = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
const res = data
.reduce((a,c)=>{
const lastIndex = a.length - 1;
if(a[lastIndex] && a[lastIndex].includes('b') && c === 'b') a[lastIndex] += c;
else a.push(c);
return a;
}, []);
console.log(res);
I don't know how to give an explanation for this but using reduce you can do it like this:
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
function merge(arr) {
return arr.reduce((acc,cur, index) => {
if(arr[index - 1] === 'b' && cur !== 'a') {
acc[acc.length - 1] = acc[acc.length - 1] + cur;
return acc;
}
acc.push(cur);
return acc;
},[]);
}
console.log(merge(ab))
Here's what you're after:
var ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
var index = 0;
var groupedArray = [];
var firstOccurence = true;
var groupedString = "";
var grouping = false;
for (var a = 0; a < ab.length; a++) {
if (ab[a] == "a") {
if (grouping) {
grouping = false;
firstOccurence = true;
groupedArray.push(groupedString);
}
groupedArray.push(ab[a]);
} else {
if (firstOccurence) {
groupedString = "";
firstOccurence = false;
}
groupedString += ab[a];
grouping = true;
}
}
console.log(groupedArray);
If you just want to merge b then you could use reduce like this:
If the current item and the previous item are b, then append it to the last accumulator item. Else, push it to the accumulator
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a']
const output = ab.reduce((acc, c, i, arr) => {
arr[i-1] === "b" && c === "b"
? acc[acc.length - 1] += c
: acc.push(c)
return acc;
},[])
console.log(output)
You can just map through the ab array and if the current element is a, push it to a new array but if the current element is b, check if the previous element is b or not, and if it is, merge the current element to the previous element else just push the b to the new array.
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
let arr = [];
ab.map((e,i) => {
if(i > 0) { // check if element is the first one or not
if(e == "b") {
if(ab[i - 1].indexOf('b') > -1) { // check if prev element is "b" or not
arr[arr.length-1] += e; // merge if prev element is "b"
} else {
arr.push(e);
}
} else {
arr.push(e);
}
} else {
arr.push(e);
}
});
console.log(arr);
N.B. The reduce() method approach and the regex approach shown in the other answers are cleaner and more concise as compared to the map() method approach shown above though.
you can stringify your array then split it with a match of b or more or any other character
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
const res = ab.join("").match(/(b{1,}|.)/g);
console.log(res)
First of all feel free to edit title if it isn't precise enough.
JS is completly not my territory.
Im trying to write this custom JS callback and, aside of the index-grabing line, it does what i require.
However since im already inside a double for-loop i have no idea how to push correct
( by correct I mean: the indexes under which each occurence of value present in 'active holder' var resided before pushing to 'partial_data' var)
indexes into indexes var. As it looks now, it will only return index of first occurence.
var full_data = ['a', 'b', 'c', 'd', 'a', 'g', 'g', 'h']
var partial_data = []
var active_holder = ['a', 'g']
var indexes = []
for (j = 0; j < full_data.length; j++) {
for (z = 0; z < active_holder.length; z++) {
if (active_holder[z].includes(full_data[j])) {
indexes.push(full_data.indexOf(full_data[j]));
partial_data.push(full_data[j]);
}
}
}
console.log(partial_data) // * ['a', 'a', 'g', 'g'] //
console.log(indexes) // * [0, 0, 5, 5] // WRONG, should be 0,4,5,6 or something along
Any suggestions please ?
You can use reduce and includes
const fullData = ['a', 'b', 'c', 'd', 'a', 'g', 'g', 'h']
const active = ['a', 'g']
let {partial, index} = fullData.reduce((op,inp,index)=>{
if( active.includes(inp) ){
op.partial.push(inp)
op.index.push(index)
}
return op
},{partial:[],index:[]})
console.log(partial)
console.log(index)
You could use reduce method and return one object with both indexes and partial data.
var data = ['a', 'b', 'c', 'd', 'a', 'g', 'g', 'h']
var active = ['a', 'g']
const {
index,
partial
} = data.reduce((r, e, i) => {
if (active.includes(e)) {
r.index.push(i)
r.partial.push(e)
}
return r
}, {
index: [],
partial: []
})
console.log(index)
console.log(partial)
You are again calling indexOf while push(). You should just push() j.
indexOf: returns the index for first occurence of value in array
var full_data = ['a', 'b', 'c', 'd', 'a', 'g', 'g', 'h']
var partial_data = []
var active_holder = ['a', 'g']
var indexes = []
for (j = 0; j < full_data.length; j++) {
for (z = 0; z < active_holder.length; z++) {
if (active_holder[z].includes(full_data[j])) {
indexes.push(j);
partial_data.push(full_data[j]);
}
}
}
console.log(partial_data) // * ['a', 'a', 'g', 'g'] //
console.log(indexes) // * [0, 0, 5, 5] // WRONG, should be 0,4,5,6 or something along
Input:
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']
Desired output:
['aaa', 'bb', 'ccc', 'd', 'ee']
Is this possible?
Edit: I forgot to mention that my previous attempt (for another example) failed, and I cannot figure out why:
let newArr = []
let last
let current
for (var i = 0; i < arr.length; i ++) {
last = last || isCurrencyArr[i]
current = isCurrencyArr[i]
let str = ''
if (last === current) {
str += arr[i]
} else {
newArr.push(str)
str = ''
}
last = isCurrencyArr[i]
}
Your example has a few hiccups. It redeclares str inside each iteration, therefore it only ever pushes empty strings. Also, it pushes the previous string when it comes across a new item, but it doesn't account for scenarios where the last items are the same, as in your example with the letter e.
If you're joining alike elements together, regardless of position...
Instead, you could use reduce() and spread syntax for object literals to build an object that keeps track of the occurrences of each item.
The object after reduce() looks like this:
{ a: "aaa", b: "bb", c: "ccc", d: "d", e: "ee" }
Once that object is built, all we have to do is create an array from the values using Object.values().
const arr = ['a', 'b', 'a', 'c', 'b', 'a', 'e', 'd', 'c', 'e', 'c'];
let items = arr.reduce((acc,i) => acc[i] ? {...acc, [i]: acc[i]+i } : {...acc, [i]: i }, {});
let result = Object.values(items);
console.log(result);
If you only want to join adjacent alike elements...
The example below uses a slightly similar approach to the above, however this reduce() outputs a string. The logic is similar to your own example: if the previous item is the same, add it to a string. If it is not, separate it and keep going.
The result is something like this: aaa|bb|ccc|d|ee. To turn that into an array, we just need to do split("|").
const arr = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e'];
let result = arr
.reduce((acc,i,idx,a) => (a[idx-1] === i || idx===0) ? acc+i : acc+"|"+i, "")
.split("|");
console.log(result);
This can be a solution to join adjacent elements:
const arr = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e'];
const resp = arr.reduce((a, e) => {
if(a.length === 0) return a.concat(e);
if(e === a[a.length - 1].split('').reverse()[0]) {
a[a.length - 1] = a[a.length - 1].split('').concat(e).join('');
return a;
}
return a.concat(e);
}, [])
console.log(resp);
Something like this should work:
function simplify(arr) {
let current = arr[0];
let final_arr = [];
let accumulated = current;
for (let i = 1; i < arr.length; i += 1) {
if (current === arr[i]) {
accumulated += arr[i];
} else {
final_arr.push(accumulated)
current = arr[i];
accumulated = current;
}
}
final_arr.push(accumulated);
return final_arr;
}
Using Array#reduce, spread syntax, and Map.
const data = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e'];
const res = [...data.reduce((a,c)=>{
return a.set(c, (a.get(c)||"") + c);
}, new Map()).values()];
console.log(res);
Algo for strictly adjacent elements.
const data = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e'];
const res = [];
for(let i = 0; i < data.length; i++){
const c = data[i];
let str = c;
for(let j = i + 1; j < data.length && c === data[j]; j++,i++){
str += c;
}
res.push(str);
}
console.log(res);