-5

I have an array which looks like

var arr = ["a|c", "a|e", "x|z"];
for(var x in arr){
    var appsplit = x.split("|");
}

If the first value(ex: a) in the elements matches then it should combine the values

Ex: output ace xz

Please advice how this approach can be done.

kind user
  • 32,209
  • 6
  • 49
  • 63
Gautam
  • 255
  • 4
  • 17
  • 1
    What's your question? Have you tried anything? Is this in javascript or java? – tnw Apr 18 '17 at 19:34
  • java != javascript – epascarello Apr 18 '17 at 19:35
  • @tnw OP has apparently tried `javascript` at Question? – guest271314 Apr 18 '17 at 19:35
  • The desired output has no sense. – kind user Apr 18 '17 at 19:36
  • So split it on the | and keep an object and append to the list. – epascarello Apr 18 '17 at 19:37
  • @Kinduser OP appears to be trying to remove duplicate characters from next array returned by `.split()` and concatenate characters – guest271314 Apr 18 '17 at 19:40
  • Don't use `for/in` loops with arrays. Use `.forEach()` or counting loops. – Scott Marcus Apr 18 '17 at 19:40
  • @guest271314 Then shouldn't be there just one element `acexz`? I'm not sure if I'm basically blind or that question is that poorly asked. – kind user Apr 18 '17 at 19:42
  • @Kinduser Not necessarily. If a match is found, concatenate current match to previous match, removing duplicate characters. Try not to "judge" Questions, here. If OP has taken time to compose Question, they perhaps, could use help; irrespective of their ability to describe the help they might need. They might not know what they need, or do not need, to achieve expected result. – guest271314 Apr 18 '17 at 19:43
  • 1
    He saying that for all values in the array that start with the same letter, combine the unique letters, in order . . . so `["a|b", "a|c", "a|d", "a|e"]`, the result would be "abcde", because the values all have "a" as their first value, and it is being combined with all of the second values, in order. Similarly, `["a|b", "a|c", "x|y", "x|z"]` would result in "abc" and "xyz". – talemyn Apr 18 '17 at 19:45

4 Answers4

1

You are testing everyone's reading comprehension with that riddle.

var pairs = {};

var arr = ["a|c", "a|e", "x|z"];
for(var x in arr)
{
    var appsplit = arr[x].split("|");
    if(pairs[appsplit[0]] !== "undefined")
    {
        pairs[appsplit[0]] = pairs[appsplit[0]] + appsplit[1];
    }
    else
    {
        pairs[appsplit[0]] = appsplit[1];
    }

}

var matches = [];

for(var x in pairs)
{
    matches.push(x + pairs[x]);
}

console.log(matches);

We need to map out the arr elements in this object called pairs. The first value in your split would be the key and the second value is appended (or assigned if it's the first match to the key)

You made an error of splitting x, but you are only splitting the index of the element, not the actual value of the element. arr[x] is the actual value, where x specifies the index in the array.

After we've gone through your arr, we can now merge the key with the values. Your output is contained in matches where the key in each pair is prepended to the value of the key's pair.

Vic
  • 633
  • 4
  • 6
  • Awesome. With slight modification this solution worked.+100 – Gautam Apr 19 '17 at 15:29
  • 1
    Note: The one drawback to this approach (and it's why I went with an array in my solution) is that the object structure does not guarantee any order to it's content., so when you do `for(var x in pairs)`, the strings may or may not come out in the order that they were created. But, if the order doesn't matter, then this will work fine. – talemyn Apr 19 '17 at 16:49
  • 1
    @talemyn Yeah, strictly speaking, it's true. But [this post](http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop) explains that most modern browsers follow order. The only exception (in Chrome), which I've experienced myself, is when you have a `key` that contains numbers only. Try pasting `{"first": 1, "1one": 2, "2": 3}` in your Chrome Dev console and watch it iterate the `"2"` key first. – Vic Apr 19 '17 at 17:13
  • @Vic - Yeah, it was only in a recent project that I finally ran into my first issue with object key order . . . unfortunately, it ended up being kind of a big one (order of execution of validation rules). I'm very keen to start digging more into `Map`, since it seems to resolve that problem with `Object`. – talemyn Apr 19 '17 at 17:47
1

Some simple code that would to the trick here.

var arr = ["a|c", "a|e", "x|z", "c|b", "z|e", "c|a"];
var resultObj = {};
arr.forEach(function(element, index){
     var array = element.split('|');
     if(array.length!==2){
        console.log("skipping, invalid input data", element);
     } else {
        var firstLetter = array[0];
        var secondLetter = array[1];
        if(resultObj[firstLetter]){
           resultObj[firstLetter].push(secondLetter);
        } else {
            resultObj[firstLetter]=[secondLetter];
        }
     }

});

Object.keys(resultObj).forEach(function(key){
    console.log(key + "," + resultObj[key]);
});
wtrocki
  • 208
  • 3
  • 6
1

You can use .reduce(), Set to not accumulate duplicate values, .some() to check if previous array contains value in current array, .map(), Array.from() and .join() to convert array to string

var arr = ["a|c", "a|e", "x|z"];
var res = arr.reduce(function(a, b) {
  var curr = b.split("|");
  var set = new Set;
  for (let prop of curr) set.add(prop);
  if (!a.length) {
    a.push(set)
  } else {
    for (prop of a) {
      if (curr.some(function(el) {
          return prop.has(el)
        })) {
        for (el of curr) {
          prop.add(el)
        }
      } else {
        for (let prop of curr) set.add(prop);
        a.push(set)
      }
    }
  }
  return a
}, []).map(function(m) {
  return Array.from([...m], function(el) {
    return el
  }).join("")
});

console.log(res);
guest271314
  • 1
  • 10
  • 82
  • 156
1

I feel like this can be done more elegantly, but I didn't have time to streamline it. :) The below code will do what you want, though:

var aStartArray = **ARRAY_VALUE_HERE**;
var aSplitResultStrings = [];

// step through each element in the array
for (var i = 0, iSALength = aStartArray.length; i < iSALength; i++) {

    // split the values for the current array element
    var aSplitVal = aStartArray[i].split("|");
    var bStringDoesNotExist = true;

    // loop through the "result strings" array
    for (var j = 0, iSRSLength = aSplitResultStrings.length; j < iSRSLength; j++) {

        // if the first letter from the array element = the first letter of the current "result string" . . .
        if (aSplitResultStrings[j].charAt(0) === aSplitVal[0]) {

            // append the second letter of the array value to the current result string
            aSplitResultStrings[j] = aSplitResultStrings[j] + aSplitVal[1];

            // indicate that a match has been found and exit the "result string" loop
            bStringDoesNotExist = false;
            break;
        }
    }

    // if there are no result strings that start with the first letter of the array value . . .
    if (bStringDoesNotExist) {

        // concatenate the two values in the current array value and add them as a new "result string"
        aSplitResultStrings.push(aSplitVal[0] + aSplitVal[1]);
    }
}

Using these arrays, the results are:

aStartArray = ["a|c", "a|e", "x|z"] //results in:
aSplitResultStrings = ["ace", "xz"]

aStartArray = ["a|b", "a|c", "a|d", "a|e", "x|y", "x|z"] //results in:
aSplitResultStrings = ["abcde", "xyz"]

aStartArray = ["a|b", "d|e", "d|f", "x|y", "g|h", "g|i", "m|n", "g|j", "a|c", "x|z"] //results in:
aSplitResultStrings = ["abc", "def", "xyz", "ghij", "mn"]

As I said, this could be more elegant (for example, you could probably use Map to make iterating through the "result strings" easier), but this makes the steps pretty clear and should get you going down the right path towards a final solution.

talemyn
  • 7,110
  • 4
  • 25
  • 45